首页 > 技术文章 > RabbitMQ消息可靠性投递解决方案 - 基于SpringBoot实现

sw008 2019-01-09 23:42 原文

原文:https://www.imooc.com/article/49814

幂等性,有序性,补偿性,可查性

生产者:

开放相应的查询接口

  • Step 1: 首先把消息信息(业务数据)存储到数据库中,紧接着,我们再把这个消息记录也存储到一张消息记录表里(或者另外一个同源数据库的消息记录表),每条消息有唯一ID,保证 业务数据+消息记录 在同一个事务中进行。

  • Step 2:生产者发送消息到MQ Broker节点(采用confirm方式发送,会有异步的返回结果,判断失败重发/降级策略)

  • Step 3、4:生产者端接受MQ Broker节点返回的Confirm确认消息结果,然后进行更新消息记录表里的消息状态。比如默认Status = 0 当收到消息确认成功后,更新为1即可!

  • Step 5:但是在消息确认这个过程中可能由于网络闪断、MQ Broker端异常等原因导致 回送消息失败或者异常。这个时候就需要发送方(生产者)对消息进行可靠性投递了,保障消息不丢失,100%的投递成功!(有一种极限情况是闪断,Broker返回的成功确认消息,但是生产端由于网络闪断没收到,这个时候重新投递可能会造成消息重复,需要消费端去做幂等处理:主键/唯一索引/update+where影响行等)。

 

补偿:

  • Step 6:最大努力尝试次数,需要有一个定时任务,把超时仍然处于中间状态的消息进行重新投递。(比如每5分钟拉取一下处于中间状态的消息,当然这个消息可以设置一个超时时间,比如超过1分钟 Status = 0 ,也就说明了1分钟这个时间窗口内,我们的消息没有被确认,那么会被定时任务拉取出来)

  • Step 7:重试多次还为成功,启动降级策略。可以在消费消息时先在redis中记入 消息ID:count重发次数  +TTL。                    降级策略可以将最终状态设置为Status = 2 ,最后交由人工解决处理此类问题(或者把消息转储到失败表或失败MQ中)。

 

消费者 :

  • 幂等设计:防止重复消费,可以利用主键/唯一索引/update+where影响行/redis等。
  • 信息验证:验证信息合法性、NPE等,防止错误消费/恶意投递。
  • 手动ACK:防止消息丢失,失败/拒绝消息重入队。
  • 更新状态:更新生产者消息表状态
  • 重试策略:防止MQ阻塞/死循环

重试消费方案1:同一消息ID避免反复重试,在消费消息时先在redis中记入 消息ID:count消费次数  +TTL,下次再消费时判断redis中次数,超次则无论失败与否都不重入队,记录失败消息内容或转发其他MQ或进入DLX或等待补偿机制。这样保证在一定时间内同一消息不会反复消费失败,避免死循环阻塞,且避免消息丢失等待补偿机制。补偿机制也可以参考redis中 消息ID:count 判断是否再次补偿。

 

 

 

推荐阅读