RocketMQ学习笔记(三)——消息丢失的场景及解决方案

今天和大家分享下RocketMQ的事务消息的实现流程分析。

在文章开始之前首先了解一个问题,RocketMQ消息在什么情况下会出现消息丢失的问题?

消息丢失的情况大致可以分为三种:

1.生产者发送消息时,由于网络故障或broker的master节点宕机,导致消息丢失。
2.消息已经发送到RocketMQ了,消息暂存在JVM堆外内存或暂存在os cache中,而后台线程还没有将消息刷到磁盘中,此时JVM系统崩溃或Linux服务宕机,导致JVM堆外内存或os cache内存数据丢失,导致消息丢失。
3.消息已经发送到RocketMQ了,但是消息消费者在消费消息的时候,还未消费完就返回ack,此时消费者宕机了,但是MQ认为消费成功了,将消费消息offset跳到了下一个消息,此时也相当于出现消息丢失的情况。

RocketMQ针对这三种情况都出了解决方案,我们逐个来分解

我们以订单系统发送消息到MQ,然后红包、短信等系统来消费这条消息的场景来描述各种解决方案的情况。

在这里插入图片描述

第一种情况的解决方案:

在这里插入图片描述

在RocketMQ中,有一个事务消息的机制,通过这个机制可以确保生产者发送的消息一定会发送到MQ中,不会出现半路丢失的情况。

在RocketMQ的事务消息机制中,生产者发送消息时会首先发送一条half消息,例如订单系统发送订单支付成功的消息到MQ,他会首先发送一条half消息,这个half消息本质就是订单消费成功的消息,但是是处于half状态,此时红包系统是无法看到这条消息的。
RocketMQ接收到这条half消息之后,会给订单系统返回一个half消息接收成功的响应,以此来通知生产者MQ正常,并且已经接收到了订单支付成功的消息。

之所以发送这样的一个消息,是为了确认MQ是否是正常运转的,是否接收到了这条消息。假设此时MQ宕机或者因为网络异常等原因,导致生产者没有接收到half消息接收成功的响应。那么生产者就会给MQ发送rollback命令,将那条half消息弃用,如果MQ返回的是half成功的响应,那么订单系统会在执行完自己的业务逻辑之后,再向MQ发送commit命令,将half消息提交,只有生产者发送了commit消息之后,half消息才会进入topic中,红包系统此时就可以消费到这条消息了。如下图所示:在这里插入图片描述
假设MQ接收到了half消息,但是在返回half消息成功响应失败了,这种情况,half消息会怎么处理呢?

其实RocketMQ有一个补偿机制,他会去扫描处于half状态的消息,如果half状态的消息一直没有执行commit/rollback操作,超过一定时间之后,会回调订单系统里的一个接口,通过这个接口用来处理这条消息是需要commit还是rollback。

第二种情况的解决方案:

在这里插入图片描述

broker的配置文件有个参数,flushDiskType,这个配置的含义是控制消息时异步刷盘还是同步刷盘,默认值是ASYNC_FLUSH,也就是异步刷盘,我们把它设置成SYNC_FLUSH,也就是同步刷盘就可以了。每次消息写入的时候,只有保证消息写入磁盘,才会认为这条消息写入成功,否则就重试写入,这样就不存在消息在缓存中丢失的问题了。
同时我们采用Raft协议主从同步的架构模式,来避免磁盘故障导致的数据丢失问题。也就是在消息写入broker中时,保证消息有多个副本,这样哪怕master节点宕机,还可以通过Dledger模式选举出新的Leader,并且新的Leader里也有完整的消息数据。这样磁盘损坏造成的消息丢失问题也就避免了。

第三种情况的解决方案:

在这里插入图片描述

消费消息的时候我们只需要注意下在返回CONSUME_SUCCESS的时候,保证业务逻辑处理完毕之后,再返回消息处理状态值,这样手动ACK的处理形式,就可以保证消费消息不丢失。同时应该尽量做好消息幂等性的处理,同样的消息处理结果一样。尽量避免异步调用回调函数consumeMessage,采用异步调用的结果,就可能会出现业务处理失败,但是返回了消息消费成功的异常情况。

RocketMQ全链路消息丢失方案总结

1.发送消息到MQ的零丢失:

方案一(同步发送消息 + 反复多次重试)
方案二(事务消息机制),两者都保证消息发送零丢失的效果,但是事务消息方案整体会更好一些

2.MQ收到消息之后的零丢失:

开启同步刷盘策略+主从架构同步机制,只要让一个Broker收到消息之后写入磁盘,同时同步复制给其他broker,然后再返回响应给生产者说写入成功,这样就可以保证MQ自己不会丢失消息了。

3.消费者消息的丢失

采用RocketMQ的消费者天然就可以保证你处理完消息后,才会提交消息的offset到broker去,只要记住别采用多线程异步处理消息的方式即可。

  • 2
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值