首页/开发/系统分析与架构设计速查/TCC(Try-Confirm-Cancel)

TCC(Try-Confirm-Cancel)

把分布式事务拆成三阶段业务操作:Try 预留资源、Confirm 确认提交、Cancel 释放预留;由业务实现三种操作,语义明确但侵入性强。

TCC 的三个阶段

TCC(Try-Confirm-Cancel)把分布式事务拆成三段业务操作:Try 检查并预留资源,Confirm 确认使用预留资源,Cancel 释放预留资源。它不依赖数据库的跨库事务,而是把“预留”做成显式的业务状态(冻结额度、占用库存),因此能跨异构系统。代价是业务侵入性强:每个参与方都要实现三种操作,并处理空回滚、悬挂与幂等等边界情况。

基本信息

Try检查并预留资源(冻结额度、占用库存)
Confirm确认使用预留资源,必须成功且幂等
Cancel释放预留资源,需处理空回滚与悬挂
协调方事务协调器负责记录全局事务状态、发起提交或回滚并做重试

典型使用场景

  • 跨行转账与结算:账户侧冻结金额,确认后扣减,失败则解冻
  • 库存与订单:下单时占用库存,支付成功后扣减,超时未支付则释放
  • 优惠券与积分:先锁定券,下单成功再核销,失败退还
  • 跨服务的额度控制:先占用授信额度,事后按实际金额结算
  • 与外部系统协同:外部系统不支持本地事务时,用两阶段业务操作替代

三阶段状态迁移

三阶段状态迁移
库存:可用 → 冻结(Try)→ 扣减(Confirm)
               ↘ 释放(Cancel)→ 可用

幂等要点:
- Confirm 重复到达:直接返回成功
- Cancel 先于 Try:记录空回滚标记
- 悬挂 Try:先查空回滚标记再执行

异常场景与处理

场景表现处理方式
空回滚Cancel 在网络超时后先于 Try 到达记录回滚标记,后续 Try 检查标记后直接拒绝
悬挂Cancel 已处理,Try 迟到并执行Try 先查回滚标记,存在则不再预留资源
重复 Confirm协调器重试导致 Confirm 多次到达幂等处理,重复请求返回成功
Confirm 失败预留资源无法最终确认重试 + 告警 + 人工介入,不能静默留下冻结资源

使用要点

  • 把“预留”当成一等业务状态管理:有独立的字段、状态机与对账口径
  • Try 阶段就要做业务校验(余额、库存、权限),确认失败要在 Try 阶段就拒绝
  • 所有三种操作都要幂等,并记录全局事务 ID 与分支事务 ID 用于对账
  • 设置事务超时与最终一致的对账任务:清理长期停留在冻结状态的预留资源
  • 为人工介入准备页面或脚本:极端情况下需要人工释放或强制确认
TCC 要把“预留”状态作为一等业务状态管理,并处理 Try 超时未达但 Cancel 先到的悬挂场景;否则会出现资源永久冻结或重复扣减。
TCC 不是唯一选择:业务能容忍延迟或可通过状态机收敛时,本地消息表、可靠事件与对账往往比 TCC 更简单,先在更轻的方案上评估复杂度。

易错点

  • Cancel 早于 Try 到达时未做空回滚保护,资源在后续 Try 中被错误预留
  • Confirm 失败未重试,出现部分提交,跨服务的业务状态长期不一致
  • 把 Try 只当接口占位不做资源校验,Confirm 阶段才发现库存或额度不足
  • 预留资源无超时与对账清理,冻结记录长期堆积,可用额度被慢慢吃掉
  • 缺少全局事务 ID 透传,出问题时无法把多个参与方的分支操作串起来排查

数据来源与参考

  • Chris Richardson《Microservices Patterns》
  • microservices.io 模式目录
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌