RabbitMQ知识

52 阅读5分钟

RabbitMQ 是基于 AMQP(高级消息队列协议)  开发的开源消息队列中间件,核心作用是实现分布式系统中不同组件间的异步通信、解耦和流量削峰,广泛应用于微服务架构、大数据处理等场景。 其核心概念有:

  • 生产者(Producer):发送消息的应用程序
  • 消费者(Consumer):接收并消费消息的应用程序
  • 服务器(Broker):Broker 就是 RabbitMQ 服务器本身,它包含了交换机(Exchange)、队列(Queue)、绑定(Binding)等核心组件,整体承担消息代理的角色
  • 虚拟主机(virtual host):起到隔离作用,每个虚拟主机相互独立,有各自的exchange
  • 交换机(Exchange):接收生产者消息并将其发送给对应的队列(Queue),是RabiitMQ的灵活路由核心
  • 队列(Queue):存储消息的容器,按先进先出的原则暂存消息直到被消费者消费
  • 绑定键(Binding):建立交换机与队列的关联,指定路由键Routing Key,用于匹配消息转发规则

基于RabbitMQ的可靠性,灵活的路由机制,消息低延迟,吞吐能力强等优点让其在MQ市场非常流行。以下介绍一下RabbitMQ知识点:

1.消息可靠性

可靠性是指生产者发送的消息并最终被消费者消费的完整流程被完成。 RabbitMQ是如何保证消息被可靠消费的呢,分别从生产者,消费者和持久化操作三方面来说

生产者:
1.RabbitMQ提供了重试策略,确保信息到达MQSpring:rabbitmq:template:retry:{重试相关配置值}
enabled:true来开启重试策略
initial-interval: 1000ms # 失败后的初始等待时间
multiplier: 2 # 失败后下次的等待时长倍数,下次等待时长 =  上次的等待时长 * multiplier
max-attempts: 3 # 最大重试次数,如果超过最大重试次数,会将数据保存入数据库后期处理
2.confirm机制:确保消息到达交换机
3.return机制:确保信息到达队列
消费者:
1.自动ack,spring:rabbitmq:listener:simple:acknowledge-mode: {} # 
有none,manual和auto三种模式,分别是不处理,手动处理以及自动处理
2.本地重试策略,与生产者重试策略一样,超过重试次数会将消息存入错误队列
3.监听错误队列,将错误队列写入数据库中后期处理
持久化保存:
RabbitMQ对消息的保存默认都是持久化,MQ宕机了也能保存已经上传的消息

2.RabbitMQ与Kafka的区别

  1. RabbitMQ是推模式,由Broker主动将消息推送给注册者,

    Kafka是拉模式,由消费自己主动去Broker中拉取信息

  2. RabbitMQ轻topic,不同的要求可以选择是否使用topic队列

    Kafka重topic,必须使用topic队列

  3. RabbitMQ阅后即焚,而Kafka不会

3.RabbitMQ如何确保消息顺序

关于这个问题,基本的解决思路就是保证同时只有一个消费者消费,方式有两种

  1. 指定消费线程数为1,此操作可以通过基于注解声明队列和交换机时在最后加上concurrency=1的设置保证
  2. MQ新增队列时增加属性x-single-active-consumer 为true

4.RabbitMQ消息积压问题

当消费者消费能力不够,或者消费者异常时就会出现消息积压问题,解决办法: 1.如果是突然的生产速度激增导致了消费能力不够,可以采用惰性队列来将生产的消息先存入磁盘,要消费时再加载到内存消费。 2.如果是消费者异常或者经常性的消费能力欠缺,则需要去修改消费者的代码或者启动临时消费者来倍速缓解消息积压的压力

5.死信交换机

死信交换机(Dead Letter Exchange, DLX)是一种处理消息队列中无法被消费的消息的方式。当消息因为某些原因(如消费者拒绝消费消息、消息过期等)而无法被正常消费时,这些消息就会成为“死信”。

为了解决死信问题,可以使用延迟队列或者延迟插件(本质延迟队列)来定期发送;即在发送消息时指定延迟时间,到达延迟时间消息被消费

6.消息重复消费问题

由于发送消息的操作是异步的,所以可能会出现一个消息被重复消费的问题。 如果有问题,我们需要对其根据实际业务作出正确的操作。

如何判断重复消费是否有问题涉及到消费者操作是否是幂等操作,即一个消息被一次和多次消费是否有区别。幂等性不能仅仅通过操作后结果是否一致来判断是否幂等,而是要结合实际业务来,通过分析操作前后的状态来判断是否幂等。

如果是幂等操作,那么消息重复消费不是问题

如果不是幂等操作,那么需要对消息作特别的操作,一般我们会对消息设置唯一ID放到reids中,在后续的操作时先通过取redis中的消息判断ID是否正在被消费,如果被消费了,那么不对该消息作操作;如果没有则正常消费消息。