探秘 RocketMQ 事务机制,如何保证消息零丢失,这些场景你熟悉吗?

引言

事务的概念就不用多说了,我相信阅读文章的童鞋都是有着非常深刻的认识。我们都知道MQ可以实现微服务之间的异步以及解耦,那么引入MQ之后,如何实现微服务之间的数据一致性是一个值得思考的问题。RocketMQ 事务消息正是解决这个问题的解决方案。另外事务消息也是为了解决消息丢失问题。

哪些场景会出现消息丢失

在分析RocketMQ事务消息之前,我们先来分析下引入消息中间件之后,整个消息链路在哪些场景会出现消息丢失的异常情况。

当我们支付订单之后,我们账户的购物积分也会进行相应的积分调整。我们结合下面的订单服务、RocketMQ、积分服务的简化交互图来看,我们来分析下整个链路中可能会出现的消息丢失问题。

场景 1:

在订单服务向 RocketMQ 发送订单成功生成的消息的时候,可能由于网络抖动的问题导致订单消息没能正常投递到 RocketMQ,导致消息丢失。

场景 2:

那么假如订单服务以及 RocketMQ 之间的网络没问题,消息正常被 RocketMQ 接收到了,那么会存在消息丢失的情况吗?答案是肯定的,这和 RocketMQ 的持久化机制有关系,当消息到达 RocketMQ 之后,并不是立马落盘存储,而是存储在 page cache 中的。如果此时出现服务器断电或者宕机情况,那么还没来得及落盘的消息数据就有可能丢失。另外即使是落到磁盘当中,如果出现磁盘坏道的话,依然会出现消息数据的可能。

场景 3:

如果前面两种场景都没问题,积分服务拿到订单消息了。还会出现消息丢失的问题吗?答案依然是肯定的。即便是积分服务拿到了订单消息,当积分服务自动提交消息 offset 到 RocketMQ 中,但是此时如果出现宕机或者积分服务挂了,没有将本该增加的积分进行处理,此时也就出现了消息丢失的情况。

事务消息机制原理

half 消息

所谓的RocketMQ事务机制,其实是RocketMQ提供了一种half消息的机制。当订单服务接受到订单支付信息后,订单服务会发送half消息到RocketMQ中,这个half消息是不被消费者所见的。怎么理解这个half信息呢,按照我自己的理解,就是它实现了一半的消息功能,只在生产端可见,在消费端不可见。另外这个half信息相当于一种RocketMQ的可用性探测,如果half消息都发送失败的话,就不必再进行下游业务的一系列操作了。

如果此时用于探测 RocketMQ 的可用性的 half 消息发送失败了,那么说明此时订单服务与 RocketMQ 存在异常,则会对之前订单进行一系列的回滚操作。如果 half 消息被成功投递,则需要进行本地事务操作,更新订单状态。

如果本地事务执行失败了怎么办,订单服务可以发送 rollback 请求,将之前的 half 消息从 RocketMQ 中进行删除,不再进行后续的消息投递。

half 消息原理分析

上文提到half消息不被消费端可见,那么这个half消息是怎么实现在RocketMQ中不被积分服务所见的呢?

订单服务发送half消息,实际并不是将消息投递到积分服务订阅的topic,而是将消息投递到RocketMQ中的RMQ_SYS_TRANS_HALF_TOPIC对应的messeageQueue。由于积分服务并没有订阅这个Topic,所以这个消息对于积分服务是不可见的。

另外有个OP_TOPIC用于记录对应half消息的commit/rollback状态。大致的交互如下如所示:

如果订单服务half消息发送失败了,由于网络原因或者RocketMQ挂了,那么此时需要执行一些回滚操作,让订单进行关闭。因为订单信息无法通知到下游服务了。

那么如果half消息已经写入RocketMQ中,但是本地事务执行失败又该怎么办呢?也就是说当订单服务接收到half消息写入成功的响应后,更新订单信息时发生了异常,无法完成状态更新。那么此时订单服务需要发送rollback的请求给RocketMQ,通知其将原来的half信息进行删除。如果本地事务执行成功,则需要发送 commit 请求给RocketMQRocketMQ会将原先存在RMQ_SYS_TRANS_HALF_TOPIC中的消息重新投递到积分服务订阅的TOPIC中去,这样积分服务就可以正常消费信息进行下一步的积分操作了。

再考虑一种情况,如果订单服务发送commit或者rollback请求未正常投递到RocketMQ中,RocketMQ不知道half消息到底是对应的本地事务到底是执行成功了还是执行失败了。针对这种情况,订单服务需要提供状态回查接口,RocketMQ定时检测是否还有没有处理的half消息,当存在这样的消息时,RocketMQ调用回查接口确认本地事务执行情况。执行失败的则删除half消息,执行成功则重新投递消息。

总结

通过上文的分析,订单服务和RocketMQ之间的交互,通过事务消息机制可以保证消息可以被可靠投递。至少在订单服务和RocketMQ之间不会出现消息丢失的问题。

最后,感谢大家的观看,谢谢大家的支持,能三连关注收藏就最好啦,祝各位面试必过,升职加薪,早日升职加薪!

【领取资料】

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

牛战士从不脱下面具

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值