3、常见分布式事务方案:TCC模式、Saga模式、可靠消息最终一致性、最大努力通知

在微服务与分布式系统架构中,单一数据库的本地事务(ACID)无法跨服务边界生效。为解决跨服务、跨数据库的数据一致性问题,业界演化出四种主流分布式事务方案。本章从原理、适用场景、优缺点三个维度进行对比分析,并给出开发环境下的选型建议。

3.1 方案总览与对比矩阵

四种方案在一致性强度、侵入性、吞吐量、回滚能力上各有侧重。下表从关键维度进行横向对比:

方案 一致性类型 业务侵入性 吞吐量 回滚能力 典型场景
TCC 强一致性(最终一致) 高(需实现三阶段接口) 中等 支持(Cancel阶段) 短事务、高一致性要求
Saga 最终一致性 中(需实现补偿逻辑) 高 支持(补偿事务) 长事务、跨多服务编排
可靠消息最终一致性 最终一致性 低(依赖消息中间件) 高 不支持(需业务补偿) 异步解耦、削峰填谷
最大努力通知 最终一致性(弱) 低(回调/轮询) 极高 不支持 非核心业务、通知类
开发环境选型提示: 在 development 环境做单元测试时,优先选择可靠消息最终一致性方案进行 Mock 测试,因其对业务代码侵入最小,便于使用嵌入式消息中间件(如 H2 + ActiveMQ/Artemis)模拟异步场景。

3.2 TCC模式(Try-Confirm-Cancel)

TCC 是一种补偿型事务方案,将整个分布式事务拆分为三个阶段:Try(预留资源)、Confirm(确认执行)、Cancel(回滚释放)。每个参与者服务都需要实现这三个接口。

  • Try 阶段: 尝试执行业务,完成资源检查和预留。例如:冻结库存、预扣余额。
  • Confirm 阶段: 如果所有参与者 Try 成功,则全局事务管理器调用 Confirm 接口,真正执行业务操作。
  • Cancel 阶段: 如果任一参与者 Try 失败或超时,则调用所有已成功 Try 的参与者的 Cancel 接口,释放预留资源。
核心特点: TCC 是业务层面的两阶段提交,不依赖数据库 XA 协议,性能优于传统 XA。但要求业务方提供三组幂等接口,开发成本较高。
TCC 模式执行流程 全局事务管理器 服务A(Try) 服务B(Try) 服务C(Try) Confirm 阶段 Cancel 阶段 说明:所有 Try 成功后进入 Confirm;任一 Try 失败则进入 Cancel,释放已预留资源

3.3 Saga模式

Saga 模式将一个长事务拆分为一组有序的子事务(本地事务),每个子事务都对应一个补偿事务。当某个子事务失败时,Saga 协调器反向调用已成功子事务的补偿操作。

  • 编排方式: 分为事件编排(Choreography)和命令编排(Orchestration)两种。前者通过事件驱动,后者由中央协调器控制。
  • 补偿设计: 补偿事务必须是幂等的,且能正确处理部分成功场景。
  • 适用场景: 跨多个微服务的业务流程,如订单创建 → 支付 → 库存扣减 → 物流发货。
注意: Saga 模式不提供隔离性(Isolation),开发环境测试时需关注脏读和幻读问题。建议在单元测试中通过 Mock 补偿逻辑来验证回滚路径。

3.4 可靠消息最终一致性

该方案通过消息中间件(如 RocketMQ、Kafka)实现事务消息,保证本地事务与消息发送的原子性。核心流程如下:

  1. 发送半消息: 生产者向 MQ 发送一条“半消息”(暂不可消费)。
  2. 执行本地事务: 生产者执行本地数据库操作。
  3. 提交/回滚消息: 本地事务成功则提交消息(消费者可见);失败则回滚消息。
  4. 消息补偿: MQ 定期回查未决消息,确保最终一致性。
可靠消息最终一致性流程 生产者服务 本地数据库 消息中间件 消费者服务 ① 发送半消息 ② 执行本地事务 ③ 结果回传 ④ 提交/回滚消息 ⑤ 投递消息 回查未决消息 说明:半消息在本地事务提交前不可消费,确保“业务操作”与“消息发送”原子性

3.5 最大努力通知

最大努力通知是最弱的一致性方案,适用于对实时性要求不高、允许短暂不一致的场景。核心思想是:发起方尽最大努力将结果通知给接收方,不保证 100% 送达。

  • 实现方式:
    • 回调通知: 发起方主动调用接收方提供的回调接口。
    • 轮询查询: 接收方定期主动查询发起方的状态。
  • 重试机制: 通常配合指数退避重试,达到最大次数后放弃或转入人工处理。
  • 典型场景: 支付结果通知、短信发送状态、第三方平台回调。
开发环境测试要点: 在单元测试中,最大努力通知通常通过 Mock 回调接口并验证重试次数来实现。建议使用 RetryTemplate(Spring Retry)模拟重试逻辑,并断言最终调用次数符合预期。

3.6 方案选型建议

在 development 环境进行单元测试与鉴权拦截测试时,建议遵循以下选型原则:

业务场景 推荐方案 单元测试关注点
资金类、库存类(强一致) TCC Try/Confirm/Cancel 三阶段幂等性、超时处理
长流程编排(订单→支付→物流) Saga 补偿事务正确性、状态机转换
异步解耦、削峰填谷 可靠消息最终一致性 半消息状态、本地事务回滚、消息重投
非核心通知、第三方回调 最大努力通知 重试次数、回调超时、降级逻辑
鉴权拦截测试提示: 在 development 环境测试分布式事务时,鉴权拦截器(如 Token 校验、权限校验)应优先于事务管理器执行。建议在单元测试中通过 @WithMockUser 或自定义 SecurityContext 来模拟已认证用户,避免鉴权逻辑干扰事务流程的验证。