问题引入

假设一个场景如下,工行用户A向建行用户B转账1万元,我们可以简单使用同步消息来处理需求,流程如下!
RocketMQ-事务消息_其他

  1. 工行系统发生一个给B加钱的同步消息M给Broker
  2. 消息被Broker成功连接后,向工行系统发送成功ACK
  3. 工行系统收到成功ACK后从用户A中扣款
  4. 建行系统从Broker中获取到消息M
  5. 建行系统消费消息M,即向用户B加钱

这种模型其实存在很大问题,如第三步从用户A中扣款失败,或者第五步给用户A加钱失败,这个对于业务来说都是毁灭性的。

解决思虑

解决思路是将第1、2、3步具有原则性,要么全部成功,要么全部失败,即消息发送成功后,必须要保证扣款成功,如果扣款失败,则要回滚发送给Broker的消息,而该思虑就是RocketMQ中的事务消息
RocketMQ-事务消息_RocketMQ_02

  1. 事务管理器TM向事务协调器TC发起指令,开启全局事务
  2. 工行系统发送给B加钱的事务消息M给TC
  3. TC会向Broker发送半事务消息prepareHalf,将消息M预提交到Broker,此时的建行系统是看不到Broker中的消息M的
  4. Broker会将预提交执行结果给Report给TC
  5. 如果提交失败,则TC会向M上报预期提交失败的响应,全局事务结束;如果预提交成功,TC会调用工行系统的回调操作,去完成工行用户A的预扣款操作
  6. 工行系统会向TC发送预扣款执行结果,即本地事务的执行状态
  7. TC收到预扣款执行结果后,会将结果上报给TM
  8. TM会根据上报结果向TC发出不同的确认指令
  • 若预扣款成功(本地事务状态为COMMIT_MESSAGE),则TM向TC发送Global Commit指令
  • 若预扣款失败(本地事务状态为ROLLBACK_MESSAGE),则TM向TC发送Global Rollback指令
  • 若现未知状态(本地事务状态为UNKNOW),则会触发工行系统的本地事务状态回查操作,回查操作会回查结果,即COMMIT_MESSAGE或ROLLBACK_MESSAGE Report给TC,TC将结果上报给TM,TM会在向TC发送最终确认指令Global Commit或者Global Rollback
  1. TC在收到指令后会向Broker与工行系统发出确认指令
  • TC接收的若是Global Commit指令,则向Broker与工行系统发出Branch Commit指令,此时Broker中的消息M才可以被建行系统看到,此时的工行用户A中的扣款操作才被确认
  • TC接受到的若是Global Rollback,则向Broker与工行系统发送Branch Rollback指令,此时Broker中的消息M将被撤销,工行用户A中的扣款操作将会被回滚

此方案是为了保证消息投递与扣款操作能够在同一个事务中,要么成功都成功,有一个失败那么就全部回滚

分布式事务

对于分布式事务,通说的说就是,一次操作由若干分支组成,这些分支操作分属于不同的应用,分布在不同的服务器上,分布式事务需要保证这些操作要么全部成功,要么全部失败,分支事务与普通事务一样,就是为了保证操作结果的一致性

事务消息

RocketMQ提供了雷士X/Open XA的分布式事务功能,通过事务消息能达到分布式事务的最终一致,XA是一种分布式事务解决方案,一种分布式事务处理模式

半事务消息

暂不能投递的消息,发送方已经成功的将发送到Broker,但是Broker未收到最终确认指令,此时该消息被标记成”暂不能投递“状态,既不能被消费者看到,处于这种状态下的消息即使半事务消息

本地事务状态

Producer回调操作执行的结果为本地事务状态,其会发送给TC,而TC会在发送给TM,TM会根据TC发送来的本地事务状态来决定全局事务确认指令

消息回查

RocketMQ-事务消息_其他_03
就是从新查询本地事务的执行状态,本例就是从新到DB中查看预扣款操作是否执行成功

RocketMQ中的消息回查设置

关于消息回查,有三个常见的属性设置,他们都在Broker加载的配置文件中配置,如下

  • transactionTimeout=20,指定TM在20秒内应该最终确认状态给TC,否者引发消息回查,默认为60秒
  • transactionCheckMax=5,指定最多回查5次,操过后将丢弃消息并记录错误日志,默认15次
  • transactionCheckInterval=10,指定设置的多次消息回查时间间隔为10秒,默认60秒

XA模式三剑客

XA(Unix Transaction) 是一种分布式事务解决方案,一种分布式事务处理模式,是基于XA协议的,XA协议由Tuxedo(分布式操作扩展之后的Unix事务系统),首先提出,并交给X/Open组织,作为资源管理器与事务管理器的接口标准,XA模式中有三个重要的组件:TC、TM、RM

TC
Transaction Coordinator,事务协调者,维护全局和分支事务的状态,驱动全局事务的提交或回滚

RocketMQ中事务消息的Broker充当TC

TM
Transaction Manager,事务管理器,定义全局事务的范围,提交或回滚全局事务,它实际是全局事务的发起者

RocketMQ中事务消息的Producer充当TM

RM
Resource Manager,资源管理器,管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚

RocketMQ中事务消息的Broker和Producer都是RM

XA模式架构

RocketMQ-事务消息_其他_04
XA模式是一个金典的2PC,其执行原理如下:

  1. TM向TC发起指令,开启一个全局事务。
  2. 根据业务要求,各个RM会逐个向TC注册分支事务,然后TC会逐个向RM发出预执行指令
  3. 各个RM在接收到指令后会在进行本地事务预执行
  4. RM将执行结果Report给TC,当然,这个结果可能是成功,可能是失败。
  5. TC在接收到各个RM的Report后会将汇总结果上报给TM,根据汇总结果TM会向TC发出确认指令
    1)若所有结果都是成功响应,则向TC发送Global Commit指令
    2)只要有结果是失败响应,则向TC发送Global Rollback指令
  6. TC在接收到指令后会再次向RM发送确认指令

RocketMQ中的事务消息并不是一个典型的XA模式,因为XA模式中的分支事务是异步的,而事务消息方案中的消息预提交和预扣款是同步的

注意

  • 事务消息不支持延迟消息
  • 对于事务消息一定要做好消息幂等性检查,因为事务消息可能不值一次消费,(因为存在回滚后在提交的情况)