RocketMQ 为什么会丢消息,如何保证消息不丢失

发布时间 2023-10-18 15:16:47作者: archaique

Producer 丢消息

1.同步发送

RocketMQ发送消息有三种模式,即同步发送,异步发送、单向发送。

  • 同步发送消息时会同步阻塞等待Broker返回发送结果,如果发送失败不会收到发送结果SendResult,这种是最可靠的发送方式。
  • 异步发送消息可以在回调方法中得知发送结果。
  • 单向发送是消息发送完之后就不管了,不管发送成功没成功,是最不可靠的一种方式。

显然,保证消息不丢失 需要采取同步发送的方式。

2.失败重试

RocketMQ 还为生产者提供了失败重试机制,同步发送和异步发送默认都是失败重试两次。当然可以修改重试次数,如果多次还是失败,那么可以采取记录这条信息,然后人工采取补偿机制。

3.事务消息???

场景:还没搞明白

半消息和普通消息的唯一区别是,在事务提交之前,对于消费者来说,这个消息是不可见的。

半消息发送成功后,订单系统就可以执行本地事务了,在订单库中创建一条订单记录,并提交订单库的数据库事务。然后根据本地事务的执行结果决定提交或者回滚事务消息。

  • 如果订单创建成功,那就提交事务消息,购物车系统就可以消费到这条消息继续后续的流程。
  • 如果订单创建失败,那就回滚事务消息,购物车系统就不会收到这条消息。

这样就基本实现了本地事务和消息发送“要么都成功,要么都失败”的原子性要求。但这个实现过程中,有一个问题是没有解决的。如果在第四步提交事务消息时失败了怎么办?

对于这个问题,Kafka 和 RocketMQ 给出了 2 种不同的解决方案。

  • Kafka 的解决方案比较简单粗暴,直接抛出异常,让用户自行处理。我们可以在业务代码中反复重试提交,直到提交成功,或者删除之前创建的订单进行补偿。
  • RocketMQ 则给出了另外一种解决方案:Broker 没有收到提交或者回滚的请求,Broker 会定期去 Producer 上反查这个事务对应的本地事务的状态,然后根据反查结果决定提交或者回滚这个事务。

 

Broker 丢消息

1.刷盘策略

场景:PageCache 异步刷盘,宕机掉电,内存 PageCache 里的消息还没来得及写入磁盘

解决措施:采用 PageCache 同步刷盘的策略

2.集群模式

主从复制同步复制

 

Consumer 丢消息

场景1:自动提交offset:消费端拉下一批数据,正在处理中自动提交了 offset这时候消费端宕机了; 重启后,拉到新一批数据,而上一批数据却没处理完。

解决措施: 取消自动提交,改为处理完了再手动提交

场景2:消息堆积,好多消息没消费,就和丢失了一样

解决措施:增加客户端实例,提高客户端消费速度