4、分布式事务模型:XA协议、TCC模式、Saga模式、本地消息表、事务消息(RocketMQ)

在分布式系统压测场景中,事务一致性是验证的核心难点。本章系统梳理五种主流分布式事务模型,从原理、适用场景到压测关注点逐一拆解,为后续gRPC接口的分布式事务压测脚本设计奠定理论基础。

4.1 分布式事务模型全景对比

五种模型在一致性强度、侵入性、性能与复杂度上各有取舍。下表从压测视角给出关键差异:

模型 一致性类型 业务侵入性 性能损耗 典型实现 压测关注点
XA协议 强一致性(ACID) 低(数据库层) 高(锁与2PC) Atomikos、Seata AT 锁等待、死锁、回滚率
TCC模式 最终一致性 高(业务代码) 中(网络开销) Seata TCC、ByteTCC Try/Cancel幂等、空回滚
Saga模式 最终一致性 中(补偿逻辑) 低(异步) ServiceComb Saga、Axon 补偿成功率、状态机超时
本地消息表 最终一致性 中(轮询+重试) 低(异步) 自研轮询任务 消息积压、重试延迟
事务消息(RocketMQ) 最终一致性 低(消息中间件) 低(半消息) RocketMQ 4.3+ 半消息超时、回查次数
压测选型建议: 强一致性场景优先XA(但需接受高锁竞争);高并发最终一致性场景优先RocketMQ事务消息或Saga;TCC适合对资源预留有严格控制的业务(如库存扣减)。

4.2 XA协议(2PC)

XA协议基于两阶段提交(2PC),由事务协调器(TM)与资源管理器(RM)协作完成。第一阶段准备(Prepare),RM锁定资源并返回就绪;第二阶段提交/回滚(Commit/Rollback),TM根据所有RM的反馈做最终决策。

XA协议(2PC)两阶段提交流程 事务协调器(TM) RM-A(数据库A) RM-B(数据库B) RM-C(消息队列) ① Prepare ① Prepare ① Prepare ② Commit/Abort ② Commit/Abort ② Commit/Abort 全局事务结果 压测风险:Prepare阶段持有数据库锁,高并发下易引发死锁;协调器单点故障会导致事务悬挂
压测陷阱: XA在Prepare阶段如果某个RM超时未响应,协调器会触发全局回滚。压测时需模拟网络延迟、RM宕机等故障,验证超时阈值与回滚效率。

4.3 TCC模式(Try-Confirm-Cancel)

TCC将每个服务接口拆分为三个阶段:Try(资源预留)、Confirm(确认执行)、Cancel(取消回滚)。业务方需自行实现幂等与补偿逻辑。

TCC模式三阶段执行流程 主调方 服务A(库存) 服务B(账户) ① Try(预留库存) ① Try(冻结金额) Confirm Confirm ② Confirm(扣减库存) ② Confirm(扣款) Cancel Cancel ③ Cancel(释放库存) ③ Cancel(解冻金额)
TCC压测关键指标:
  • Try成功率:资源预留失败率过高会直接导致事务失败。
  • Confirm/Cancel幂等性:网络重试可能导致重复调用,需验证幂等处理。
  • 空回滚:Try未执行但Cancel被调用时,业务必须能正确处理。

4.4 Saga模式

Saga将长事务拆分为多个本地事务,每个本地事务对应一个补偿事务。执行过程中若某一步失败,则按反向顺序依次调用补偿操作。Saga分为编排(Choreography)与协调(Orchestration)两种实现方式。

Saga编排模式(Choreography)——事件驱动 订单服务 库存服务 支付服务 物流服务 订单创建 库存扣减 支付成功 补偿:取消订单 补偿:释放库存 补偿:退款 支付失败 压测重点:补偿链路成功率、补偿幂等性、状态机超时恢复、事件总线吞吐量

4.5 本地消息表

本地消息表的核心思想是将业务操作与消息发送放在同一个本地事务中。业务表更新成功后,消息记录写入本地消息表;后台轮询任务扫描未发送的消息,异步投递到MQ,下游消费方处理成功后回调确认。

-- 本地消息表结构示例
CREATE TABLE local_message (
    id          BIGINT PRIMARY KEY AUTO_INCREMENT,
    biz_id      VARCHAR(64)   NOT NULL COMMENT '业务ID',
    msg_body    TEXT          NOT NULL COMMENT '消息体(JSON)',
    status      TINYINT       NOT NULL DEFAULT 0 COMMENT '0-待发送 1-已发送 2-已确认',
    retry_count INT           NOT NULL DEFAULT 0,
    create_time DATETIME      NOT NULL,
    update_time DATETIME      NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
压测关注点:
  • 轮询间隔:间隔太短增加DB压力,太长增加延迟。
  • 重试次数与指数退避:避免死循环或消息丢失。
  • 消息表清理策略:历史数据堆积会影响查询性能。

4.6 事务消息(RocketMQ)

RocketMQ事务消息通过半消息(Half Message)与事务回查机制,将本地事务与消息发送解耦为原子操作。流程如下:

  1. 发送半消息:生产者向RocketMQ发送半消息(对消费者不可见)。
  2. 执行本地事务:生产者执行本地业务逻辑。
  3. 提交/回滚:根据本地事务结果,向MQ发送Commit或Rollback指令。
  4. 事务回查:若MQ长时间未收到Commit/Rollback,主动回调生产者查询事务状态。
  5. 消费者消费:只有Commit后的消息才会被消费者可见并消费。
RocketMQ事务消息执行流程 生产者 RocketMQ Broker 消费者 本地数据库 ① 发送半消息 ② 执行本地事务 ③ Commit/Rollback ④ 投递消息 回查事务状态 压测关键参数:半消息超时时间(默认15s)、回查最大次数(默认15次)、回查间隔(默认60s) 压测场景:模拟回查超时、回查接口失败、半消息堆积、消费者处理延迟

4.7 五种模型压测场景总结

模型 压测场景设计 故障注入点 关键指标
XA 高并发写入、Prepare阶段超时 RM宕机、网络分区、协调器崩溃 锁等待时间、死锁率、回滚率
TCC Try资源竞争、Cancel幂等重试 Confirm/Cancel接口超时、空回滚 Try成功率、补偿成功率、幂等性
Saga 长链路补偿、状态机超时 中间节点失败、补偿链路断裂 补偿成功率、状态机恢复时间
本地消息表 消息积压、轮询延迟 DB连接池耗尽、消息表锁竞争 消息投递延迟、积压量、重试次数
事务消息 半消息超时、回查接口压力 回查接口失败、Broker宕机 半消息超时率、回查成功率、吞吐量
压测前置提醒: 无论选择哪种模型,压测前必须确认业务接口的幂等性与补偿逻辑已完整实现。分布式事务压测不仅是性能验证,更是容错能力与数据一致性的全面检验。