ROCKETMQ

消息队列(四)如何处理消息丢失的问题?

一、为什么消息会丢失?跟消息重复问题类似,消息丢失也可能出现在生产者、MQ、消费者三者中。这三者导致消息丢失的原因是什么呢?生产者:生产者推送消息到MQ中,由于网络抖动等原因消息没有推送到MQ中,或者消息推送到MQ中了但是MQ内部出错了,导致消息丢失。MQ:MQ接收到消息后先把消息暂存在OSCache中,消费者还没消费的时候MQ自己挂了,导致消息丢失。消费者:消费者消费到了这条消息,但是还没来得及

一、为什么消息会丢失?

跟消息重复问题类似,消息丢失也可能出现在生产者、MQ、消费者三者中。这三者导致消息丢失的原因是什么呢?

  • 生产者:生产者推送消息到 MQ 中,由于网络抖动等原因消息没有推送到 MQ 中,或者消息推送到 MQ 中了但是 MQ 内部出错了,导致消息丢失。

  • MQ:MQ 接收到消息后先把消息暂存在 OS Cache 中,消费者还没消费的时候 MQ 自己挂了,导致消息丢失。

  • 消费者:消费者消费到了这条消息,但是还没来得及处理,消费者自己挂了,但是消费者已经告诉了 MQ 自己已经消费完了,导致消息丢失。

二、如何解决消息丢失的问题

不同的消息队列解决消息丢失的方法是不同的,下面分别介绍不同 MQ 是如何解决消息丢失问题的。

1、RabbitMQ

1.1 生产者导致消息丢失

RabbitMQ 有两种方案可以避免消息丢失,一种是 RabbitMQ 的事务机制,一种是 Confirm 模式。这里先看一下事务机制。


RabbitMQ 客户端中 Channel 接口有这么几个函数,channel.txSelect 用来开启一个事务,channel.txCommit 用来提交事务,channel.txRollback 用来回滚事务。为了避免消息丢失,我们可以在发送消息前,先开启执行 txSelect 方法开启一个事务,接着发送消息,如果消息投递失败,执行 txRollback 回滚事务,再执行重试操作重新发送,如果消息投递成功,执行 txCommit 方法提交事务。


这个方案可以保证我们的消息一定是投递成功的,但是几乎没有人使用这种方案。因为这个方案是同步阻塞的,也就是一条消息发送后,一定要等到 MQ 回应之后执行了提交或回滚事务操作,才能继续往下执行。大致过程如下图所示:


RabbitMQ 还提供了另一种方法避免生产者消息丢失问题,那就是 Confirm 模式。Confirm 模式是这样子的,生产者发送消息后,不需要等待 MQ 的回应,MQ 接收成功后,会回调生产者的 ack 接口通知生产者消息投递成功了,如果 MQ 接收失败,会回调 nack 接口通知生产者消息投递失败了,生产者可以重新对这条消息进行投递。大致过程如

原创不易,完成人机校验,阅读全文

相关推荐