以XA模式为基础,详解RocketMQ的事务消息

76 阅读5分钟

XA模式

XA 模式是一种基于 X/Open 组织定义的 XA 规范的分布式事务处理解决方案,用于在分布式系统中协调多个资源管理器,以保证事务的原子性、一致性、隔离性和持久性(ACID)。

XA模式中有三个核心组件:TC、TM、RM。

  • 事务协调者(TC) : 维护全局和分支事务的状态,驱动全局事务提交或回滚。在RocketMQ中Broker充当着TC。
  • 事务管理器(TM) :负责协调和管理全局事务,决定事务的开始、提交或回滚,是整个分布式事务的核心控制者。在RocketMQ中Producer充当着TM。
  • 资源管理器(RM) :负责管理具体的资源,如数据库、消息队列等,每个 RM 都要实现 XA 接口,以便与 TM 进行通信。在RocketMQ中Producer和Broker都充当着RM。

架构

XA模式是一个典型的两阶段提交协议(Two-Phase Commit Protocol) ,其执行原理如下:

  1. TM向TC发起指令,开启一个全局事务。

  2. 根据业务要求,各个RM会逐个向TC注册分支事务,然后TC会逐个向RM发出预执行指令。

  3. 各个RM在接收到指令后会在进行本地事务预执行。

  4. RM将预执行结果Report给TC。

  5. TC在接收到各个RM的Report后会将汇总结果上报给TM,根据汇总结果TM会向TC发出确认指令。

  • 若所有结果都是成功响应,则向TC发送Global Commit指令。
  • 只要有结果是失败响应,则向TC发送Global Rollback指令。
  1. TC在接收到指令后再次向RM发送确认指令。

RocketMQ的事务消息

概念

分布式事务

一次操作由若干分支操作组成,这些分支操作分属不同应用,分布在不同服务器上。分布式事务需要保证这些分支操作要么全部成功,要么全部失败。

事务消息

RocketMQ提供了类似X/Open XA的分布式事务功能,通过事务消息能达到分布式事务的最终一致。

半事务消息

暂不能投递的消息,发送方已经成功地将消息发送到了Broker,但是Broker未收到最终确认指令,此时该消息被标记成“暂不能投递”状态,即不能被消费者看到。

本地事务状态

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

public enum LocalTransactionState {
COMMIT_MESSAGE, // 本地事务执行成功
ROLLBACK_MESSAGE, // 本地事务执行失败
UNKNOW, // 不确定,表示需要进行回查以确定本地事务的执行结果
}

消息回查

当回调操作返回UNKNOWN,或者TC没有接收到TM的最终全局事务确认指令时,便会进行消息回查,重新查询本地事务的执行状态。

流程举例

这是一个扣款付款的场景,但如果不使用事务消息,可能会存在问题:若第3步中的扣款操作失败,但消息已经成功发送到了Broker。对于MQ来说,只要消息写入成功,那么这个消息就可以被消费。此时建行系统中用户B增加了1万元。出现了数据不一致问题。

因此需要事务消息,将1、2、3步骤变为一个整体,即保证这三个步骤的原子性。

  1. TM向TC发起指令,开启全局事务

  2. 工行系统发一个给B增款1万元的事务消息M给TC

  3. TC会向Broker发送半事务消息,将消息M预提交到Broker。此时的建行系统是看不到Broker中的消息M的

  4. Broker上报预提交结果给TC

  5. 如果预提交失败,则TC会向TM上报预提交失败的响应,全局事务结束;如果预提交成功,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中的扣款操作将被回滚

注意

  • 事务消息不支持延时消息
  • 事务消息需要做好消息幂等处理
  • 事务消息方案并不是一个典型的XA模式。因为XA模式中的分支事务是异步的,而事务消息方案中的消息预提交与预扣款操作间是同步的。