当前位置: 首页 > 科技观察

谈谈你对RocketMQ的分布式事务原理的理解

时间:2023-03-19 19:14:29 科技观察

一位工作五年的小伙伴在面试的时候被问到RocketMQ的分布式事务实现原理。他说,他只知道RocketMQ可以支持事务,但并没有了解它的事务实现原理。今天,我就和大家分享一下我对这个问题的理解。1、分布式事务应用场景随着应用的拆分,从单体架构到分布式架构,每个服务或模块也会有自己的数据库。一个业务流程的完成需要多次接口调用或者发送多条MQ消息。浪漫与悲观并不冲突。我经常消极但仍然觉得生活很美好。哪怕只是一缕光入室,我也必须认真对待。那么问题来了,如果执行多条SQL语句,数据库的本地事务是可以保证原子性的。浪漫与悲观并不冲突。我经常消极但仍然觉得生活很美好。哪怕只是一缕光入室,我也必须认真对待。但是,如果是一个SQL操作和一个MQ操作,怎么能在同一个逻辑单元执行呢?是先执行SQL还是先发送MQ?浪漫与悲观并不冲突。我经常消极但仍然觉得生活很美好。哪怕只是一缕光入室,我也必须认真对待。我们分析一下情况,如果是先发送MQ消息,然后再执行SQL。这时候会分为两种情况:第一种情况:如果发送MQ失败了,SQL当然不会执行了。情况二:如果MQ发送成功,但是本地数据库SQL执行失败。比如网络异常,主键重复,或者字段过长等等,浪漫和悲观并不冲突。我经常消极但仍然觉得生活很美好。哪怕只是一缕光入室,我也必须认真对待。也就是说,下游的业务系统已经拿到了最新的数据,而自己本地的数据库还没有。此时本地数据库中的数据和其他系统注册的数据不一样,发送的消息无法撤回,可能已经被消费了。这被称为不堪重负的水。浪漫与悲观并不冲突。我经常消极但仍然觉得生活很美好。哪怕只是一缕光入室,我也必须认真对待。因此,在分布式应用场景下,我们需要调整代码执行流程,即必须先操作本地数据库,再发送MQ消息。如果本地数据库SQL执行成功,即使MQ消息发送失败,MQ仍然可以重发。2.分布式事务实现原理基于以上应用场景,发送消息的过程应该如何设计,使这两个操作要么成功,要么都失败?其实可以参考XA两阶段提交的思想,把消息的发送分成两步,然后在这个过程中包含对本地数据库的操作。那么在介绍原理之前,先科普一下两个新的概念:1.HalfMessage:即暂时无法投递给消费者的消息。发送方已经成功将消息发送给MQ服务器,但是服务器还没有收到生产者对消息的二次确认。此时,该消息将被标记为“暂时无法送达”。2、消息状态检查:当某个交易消息的二次确认由于网络中断、生产者应用重启等原因丢失时,MQ服务器扫描发现某个消息处于“半消息”状态一段时间很长一段时间,你需要主动向消息生产者询问消息的最终状态,是Commit还是Rollback。下面介绍一下RocketMQ的分布式事务实现原理。如图,分为七个步骤:浪漫与悲观不冲突。我经常消极但仍然觉得生活是美好的,即使它只是一束光。房间也非常重视它的到来。第一步:生产者向MQ服务器发送消息。第二步:MQ服务器持久化消息成功后,用ACK向发送方确认消息发送成功,此时消息为半条消息。第三步:发送方开始执行本地数据库事务逻辑。第四步:发送端根据本地数据库事务的执行结果向MQServer提交二次确认。当MQServer收到Commit状态时,将半个消息标记为可交付,订阅者最终会收到消息;MQ服务器收到回滚状态。如果删除了一半的消息,订阅者将不会接受该消息。第五步:在断网或者应用重启等特殊情况下,按照第四步提交的二次确认最终没有到达MQServer,MQServer会在一定时间后发起对该消息的消息校验。第六步:发送方收到消息校验后,需要校验相应消息本地事务执行的最终结果。第七步:发送方根据检查得到的本地事务的最终状态重新提交二次确认,MQServer仍然按照第四步(Commit/Rollback)对半消息进行操作。好了,以上就是我对RocketMQ分布式事务的理解。