浅谈 RabbitMQ(二)解决消息丢失

浅谈 RabbitMQ(一)工作模型与 Exchange 类型

一、消息传递分析

RabbitMQ的具体结构图参考笔者上一篇文章,下面画个消息传递的简图

image

从上图可知,要确保一个消息正确的传递,需要在四个传递阶段都能正确传递:

  1. 确保消息成功由生产者发送到RabbitMQ服务器
  2. 确保消息被交换机路由到正确的队列
  3. 确保消息在队列中不丢失
  4. 确保消息成功被消费者消费

二、消息丢失的几种情况

知道了消息如何传递,自然也就知道了消息丢失的情况了:

  1. 在生产者发送到RabbitMQ服务器时丢失
  2. 在交换机路由到队列时丢失
  3. 在队列中丢失
  4. 在消费时丢失

三、消息丢失解决方案

那么解决消息丢失自然也是根据这几种情况来分析了:

(1)解决生产者发送消息到MQ的丢失

1. 服务端确认-事务模式

image

生产者每发送一次消息,MQ就响应一次。这种模式效率低,不推荐

2. 服务端确认-确认模式

image

生产者发送消息后,服务器发送确认ACK给生产者,根据确认的方式又分为三种:

  1. 单条确认:生产者每发送一次消息,服务器发送确认一次,类似于事务模式,效率低
  2. 批量确认:设置发送消息次数后,服务器发送确认
  3. 异步确认:生产者监听服务器发送的确认事件,由服务器决定何时确认

(2)解决在交换机路由时的消息丢失

  1. 在无法路由到队列时将消息回发给生产者

  2. 创建交换机时指定一个备份交换机,路由失败时将消息发送到备份交换机

(3)解决在队列时的消息丢失

  1. 创建队列时设置队列持久化
  2. 消息持久化

(4)解决在消费时的消息丢失

消费者消费消息时默认为自动确认,即消费者刚收到消息时就给MQ发送ACK确认,此时MQ会将消息出队;如果想要在消费的逻辑处理完成后再确认消息,就需要消费者设置手动确认ACK,假如在消费过程中发生异常,无法发送确认给MQ服务器,消息将无法出队,导致堆积,所以需要在finally块中设置unAck或者将消息回发给MQ服务器

(5)其它保证消息正确消费的情况

  1. 补偿机制

比如生产者在发送消息到MQ时,始终收不到确认,那么就需要重发消息,但是重发也不能一直发送,会导致重复消息堆积。所以有两种解决方案:① 设置等待确认超时,超时后再重发消息;② 重发时控制次数

  1. 消息幂等

假如在消费过程中同一消息被消费多次,在特定场景中将产生重大影响,比如转账等,所以需要保证同一条消息在消费多次后保证操作一致(类似于接口幂等性:重复调用时保证数据一致)

posted @ 2021-08-16 13:40  超级鲨鱼辣椒  阅读(364)  评论(0编辑  收藏  举报