【RabbitMQ+消息可靠性+消息重复消费问题+消息积压问题+死信交换机】

为什么使用 MQ?MQ 的优点

• 异步处理 - 相比于传统的串行、并行方式,提高了系统吞吐量。
• 应用解耦 - 系统间通过消息通信,不用关心其他系统的处理。
• 流量削峰 - 可以通过消息队列长度控制请求量;可以缓解短时间内的高并发请求。
• 日志处理 - 解决大量日志传输。
• 消息通讯 - 消息队列一般都内置了高效的通信机制,因此也可以用在纯的消息通讯。比如实现点对点消息队列,或者聊天室等。

  • 总结:解耦,异步,削峰

消息队列有什么优缺点?RabbitMQ 有什么优缺点?

  1. 系统可用性降低
    本来系统运行好好的,现在你非要加入个消息队列进去,那消息队列挂了,你的系统不是呵呵了。因此,系统可用性会降低;
  2. 系统复杂度提高
    加入了消息队列,要多考虑很多方面的问题,比如:一致性问题、如何保证消息不被重复消费、如何保证消息可靠性传输等。因此,需要考虑的东西更多,复杂性增大。
  3. 一致性问题
    A 系统处理完了直接返回成功了,人都以为你这个请求就成功了;但是问题是,要是 BCD 三个系统那里,BD 两个系统写库成功了,结果 C 系统写库失败了,咋整?你这数据就不一致了。
    所以消息队列实际是一种非常复杂的架构,你引入它有很多好处,但是也得针对它带来的坏处做各种额外的技术方案和架构来规避掉,做好之后,你会发现,妈呀,系统复杂度提升了一个数量级,也许是复杂了 10 倍。但是关键时刻,用,还是得用的。

几款消息中间件的对比:

在这里插入图片描述

  • 追求可用性:Kafka、 RocketMQ 、RabbitMQ
  • 追求可靠性:RabbitMQ、RocketMQ
  • 追求吞吐能力:RocketMQ、Kafka
  • 追求消息低延迟:RabbitMQ、Kafka
    在这里插入图片描述

RabbitMQ

  • RabbitMQ 是一款开源的,Erlang 编写的,基于 AMQP 协议的消息中间件
  • 基本概念
  1. • Broker: 简单来说就是消息队列服务器实体
  2. • Exchange: 消息交换机,它指定消息按什么规则,路由到哪个队列
  3. • Queue: 消息队列载体,每个消息都会被投入到一个或多个队列
  4. • Binding: 绑定,它的作用就是把 exchange 和 queue 按照路由规则绑定起来
  5. • Routing Key: 路由关键字,exchange 根据这个关键字进行消息投递
  6. • VHost: vhost 可以理解为虚拟 broker ,即 mini-RabbitMQ server。其内部均含有独立的 queue、exchange 和 binding 等,但最最重要的是,其拥有独立的权限系统,可以做到 vhost 范围的用户控制。当然,从 RabbitMQ 的全局角度,vhost 可以作为不同权限隔离的手段(一个典型的例子就是不同的应用可以跑在不同的 vhost 中)。
  7. • Producer: 消息生产者,就是投递消息的程序
  8. • Consumer: 消息消费者,就是接受消息的程序
  9. • Channel: 消息通道,在客户端的每个连接里,可建立多个 channel,每个 channel 代表一个会话任务
    由 Exchange、Queue、RoutingKey 三个才能决定一个从 Exchange 到 Queue 的唯
    一的线路。
  • rabbitmq 的使用场景

(1)服务间异步通信
(2)顺序消费
(3)定时任务
(4)请求削峰

  • RabbitMQ事务是怎么实现的?
  • 事务的实现主要是对信道(Channel)的设置,主要的方法有三个:
  1. channel.txSelect()声明启动事务模式;
  2. channel.txCommit()提交事务;
  3. channel.txRollback()回滚事务;
  4. 使用事务机制,当生产者向 RabbitMQ 发送消息时,需要在 channel.txSelect() 后,先将消息发布到队列中,再使用 channel.txCommit() 提交事务。这种方式可以确保如果有任何错误发生,整个事务将被回滚,因此可以保证 RabbitMQ 接收和处理消息的可靠性,但是会带来额外的性能损失,因此在性能要求不严格的场景下使用。使用事务机制,当生产者向 RabbitMQ 发送消息时,需要在 channel.txSelect() 后,先将消息发布到队列中,再使用 channel.txCommit() 提交事务。这种方式可以确保如果有任何错误发生,整个事务将被回滚,因此可以保证 RabbitMQ 接收和处理消息的可靠性,但是会带来额外的性能损失,因此在性能要求不严格的场景下使用。事务机制的性能通常比非事务机制低,因此不建议在性能要求较高的场景下使用。

1. 消息可靠性

  • 消息丢失的几种情况:
  1. 生产者发送消息未到达交换机
  2. 消息达到交换机,但是没有正确路由到队列
  3. MQ宕机,队列中的消息不见了
  4. 消费者收到消息,还没有消费,消费者就宕机了
  • 那么消息能不能丢呢?
  1. 不太重要的消息,丢了也没事
  2. 重要的消息,跟事务数据一致性相关的消息,不能丢失的
  • 如何确保消息不丢失?
  1. 生产者开启confirm机制,保证消息正确到达交换机
  2. 生产者开启return机制,保证消息正确到达队列
  3. 交换机,队列。消息进行持久化(默认都是持久化)
  4. 消费者开启手动ack ;或者自动ack(配置文件)+重试次数耗尽执行失败策略(定义消息消费失败重试次数);定义一个错误交换机队列,将失败的消息投递到队列,后期用过人工进行干预。
  • ack机制:
  • 在这里插入图片描述
  • ack的取值:
  1. none:只要消息到达消费者,Spring直接返回ack到MQ
    在这里插入图片描述
  2. manual:手动ack;
  • 消费成功,调用API给MQ返回ack
  • 消费失败,调用API给MQ返回nack,并且让消息重回队列
    在这里插入图片描述
  • 代码实现:
    在这里插入图片描述
  1. auto:自动ack;
  • 消费消息不出异常,返回ack给MQ
  • 消费消息出异常了,返回nack,把消息重回队列
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    需求:把消息投递到失败的交换机,路由队列。记录日志,将来人工干预。

2. 消息重复消费问题

  • 概述:

因为网络传输等等故障,确认信息没有传送到消息队列,导致消息队列不知道自己已经消费过该消息了,再次将消息分发给其他的消费者。

  • 同一条消息被多次消费是否会有问题?

不一定,看情况

  • 幂等性操作
  1. 多次执行同一个操作,结果都是一样的
  2. 常见的幂等性操作有:
    在这里插入图片描述
  3. 常见的非幂等性操作:
    在这里插入图片描述
  • 对于非幂等性操作,多次消费消息,会造成数据一致性问题,所以要保证重复消费消息的问题

生产者再发送消息的时候,为每一条消息设置一个全局唯一的messageId,消费者拿到后,使用setnx命令,将messageId作为key放到redis中:setnx(messageId,1),若返回1,说明之前没有被消费过,可以正常消费,若返回0,就说明这条消息之前就被消费过,抛弃掉;

3. 消息积压问题

  • 概述:

生产者生产消费的速度远高于消费者消费消息的速度,于是就会造成消息积压在MQ队列中

  • 消息积压问题解决
  1. 查看是否是设计问题:
    如果是,重新设置生产者与消费者数量匹配。
  2. 消费者出现问题:
    2.1 消费者出现异常,解决消费者代码
    2.2 消费者宕机,临时开启多个消费者,来以倍速消费积压的消息。当积压的消息消费的差不多的情况,关闭临时消费者。
  3. 消息队列满了以后该怎么处理?
    没办法了,说明紧急扩容也来不及了,只能“丢弃+批量重导”了,写程序快速消费,然后重导。

4. 死信交换机

  • 成为死信的几种情况:
  1. 消费者使用basic.reject 或 basic.nack声明消费失败,并且消息的requeue(重入队列)参数设置为false
  2. 消息是一个过期消息,超时无人消费
  3. 要投递的队列消息满了,无法投递
  • 死信交换机
  1. 如果这个包含死信的队列配置了 dead-letter-exchange 属性,指定了一个交换机,那么队列中的死信就会投递到这个交换机中,而这个交换机称为 死信交换机 (Dead Letter Exchange,检查DLX)。
  2. 死信交换机的路由过程:
    在这里插入图片描述
  • TTL
  • 超时未消费,消息变成死信的两种情况
  1. 消息本身设置了超时时间
  2. 消息所在的队列设置了超时时间
  3. 如果两者都设置了超时时间,短时间优先
  • 延时队列
  • 概述:一种实现 消费者延迟收到消息 的模式
  • 实现延时队列

1.在RabbitMQ中,没有延迟队列的功能。可以使用 TTL + 死信队列 的方式实现延迟队列
2. DelayExchange插件;官网:

  • https://blog.rabbitmq.com/posts/2015/04/scheduling-messages-with-rabbitmq
    在这里插入图片描述
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值