{T}

如何在业务中体现 TCC 事务模型?

0. 引言

TCC(Try-Confirm-Cancel)是分布式事务中的"业务补偿派"代表:把每个资源操作拆成预留(Try)、确认(Confirm)、取消(Cancel)三个业务方法,由事务管理器统一编排。相比 2PC 的"数据库锁资源",TCC 把资源控制权交给业务代码——更灵活、性能更好,但侵入性也最高。本文用转账场景讲透 TCC 的流程与三大难题。

1. TCC 的核心思想

图表渲染中…
方法语义转账示例(账户 A → B 转 100)
Try尝试:预留资源,保证 Cancel 或 Confirm 可执行A 余额扣减到"冻结"字段;B 增加"预收"字段
Confirm确认:Try 成功后真正执行(幂等)A 冻结转扣减;B 预收转入账
Cancel取消:释放 Try 预留的资源(幂等)A 冻结回余额;B 预收清零

关键特征:Try 不真正扣减,只是"占位"——这样 Confirm/Cancel 都基于 Try 的预留结果执行,全局事务管理器可以安全地决定提交或回滚。

2. TCC 完整流程(转账示例)

图表渲染中…
  • 所有 Try 成功 → 全局 Confirm;任一 Try 失败 → 全局 Cancel;
  • 每个方法必须幂等(Confirm/Cancel 可能被重试);
  • 事务管理器负责记录全局状态、驱动各分支、处理超时重试。

3. TCC 的三大难题

难题场景解法
空回滚Try 因网络超时未到达,但 Cancel 先到了——Cancel 执行时资源从未被预留事务控制表记录分支状态:Cancel 前检查 Try 是否执行过,未执行则直接返回成功并记录"已空回滚"
幂等Confirm/Cancel 因网络重试被重复执行——重复扣款/重复入账唯一事务 ID + 状态机:同一分支只执行一次 Confirm/Cancel(幂等表/状态字段)
悬挂Try 超时被 Cancel(空回滚),但 Try 请求延迟到达并执行了预留——资源被永久冻结事务控制表中记录"已空回滚",Try 到达时发现已回滚则拒绝执行(防悬挂)
text
典型时序(悬挂问题):
① Try 发送超时 → ② TM 判定失败 → ③ Cancel 执行(空回滚,记录状态)
  → ④ 迟到的 Try 到达 → 必须拒绝(否则资源被冻结且无人释放)

三者合起来要求:Try、Confirm、Cancel 都要访问"事务控制表"做状态校验——这是 TCC 落地的最大工作量,也是框架(Seata)帮你做的事情之一。

4. TCC vs 2PC vs 普通补偿

维度2PC/XATCC普通补偿(Saga)
资源控制数据库锁(资源级)业务冻结(业务级)无预留,直接执行再回补
一致性强一致最终一致(Try 后可见中间态)最终一致
侵入性低(SQL 级)(三方法 + 控制表)中(补偿逻辑)
性能低(锁等待)中(无长锁,但多轮调用)高(异步)
适用低并发跨库资金类强管控长流程可异步

5. Seata 中的 TCC 落地

java
@LocalTCC
public interface AccountAction {
    @TwoPhaseBusinessAction(name = "deduct", commitMethod = "confirmDeduct", rollbackMethod = "cancelDeduct")
    boolean tryDeduct(@BusinessActionContextParameter(paramName = "accountId") String accountId,
                      @BusinessActionContextParameter(paramName = "amount") BigDecimal amount);

    boolean confirmDeduct(BusinessActionContext ctx);
    boolean cancelDeduct(BusinessActionContext ctx);
}
  • @LocalTCC + @TwoPhaseBusinessAction 声明三方法,Seata 自动管理空回滚/幂等/悬挂的控制表branch_table);
  • Confirm/Cancel 由 Seata 在全局事务提交/回滚时自动调用(含重试与幂等);
  • 业务只需关注三方法的业务实现,框架解决状态难题。

6. 小结

  • TCC = Try 预留 → Confirm 确认 / Cancel 取消,资源控制下沉到业务层;
  • 三大难题是落地的试金石:空回滚、幂等、悬挂,统一靠"事务控制表 + 状态机"解决;
  • TCC 适合资金类强管控:中间态可控(冻结/预收)、无长锁、最终一致;
  • 框架(Seata/ByteTCC)承担状态管理,业务侧重点是三方法的正确性与幂等实现

下一章讲解分布式锁的应用场景与实现方案对比:数据库、Redis、ZooKeeper、etcd。