TCC 与三大坑(空回滚/幂等/悬挂)

distributed-transaction 📚 learning tcc-pitfalls · distributed-transaction · tcc · empty-rollback · idempotency · dangling · compensation · reconciliation

TL;DR(30 秒扫完)

  • TCC 三方法:Try 冻结资源 / Confirm 确认提交 / Cancel 取消补偿
  • 三大坑:空回滚(Try 未执行但 Cancel 到达)/ 幂等(Confirm/Cancel 重试)/ 悬挂(Confirm 先到被拒 Try 后到)
  • 三大坑解决方案:Try 标记表 / 业务单号唯一键 / 事务状态表
  • 失败处理 6 步链路:失败记录 → 幂等重试 → 超时兜底 → 告警 → 对账 → 人工
  • 关键金句:重试的前提是幂等,幂等的前提是三大坑都处理好
  • 对账是终极兜底:TCC 不是 100% 可靠,极端故障下靠对账发现不一致

关键结论

结论 ATCC 三大坑(空回滚/幂等/悬挂)必须同时处理,缺一不可
结论 B重试的前提是幂等,否则重试会重复扣款/重复发货
结论 CSeata TCC 框架已自动处理三大坑,自建 TCC 必须自己处理
结论 D对账系统是终极兜底,TCC + 对账 + 人工兜底是大厂金融标配

完整讲解(费曼四步)

STEP 1 · 概念

TCC(Try-Confirm-Cancel):业务显式实现三个方法的分布式事务模式,Try 冻结资源、Confirm 提交、Cancel 补偿。

STEP 2 · 大白话

TCC 类比:你要买房,先交定金(Try),开发商确认合同(Confirm),最后过户(提交)。如果中间出问题,定金退还(Cancel)。
  • Try = 交定金(冻结资源,不实际扣款)
  • Confirm = 确认合同(真的扣款)
  • Cancel = 定金退还(释放冻结)
三大坑类比:
  • 空回滚 = 你还没交定金,但开发商说"退还定金"(Try 未执行但 Cancel 到达)
  • 幂等 = 开发商重复让你签合同(Confirm 重试),重复扣款
  • 悬挂 = 开发商先让你签合同但你还没交定金,然后你才交定金(Confirm 先到被拒,Try 后到)

STEP 3 · 底层

TCC 三方法语义

方法动作示例(转账)
Try冻结资源冻结 A 账户 100 元(不实际扣款)
Confirm确认提交真实扣款 A 账户 100 元
Cancel取消补偿释放 A 账户冻结的 100 元

三大坑详解

坑触发条件表现解决方案
空回滚Try 因网络问题从未执行,但 Cancel 因协调者崩溃恢复而到达Cancel 操作不存在的资源Try 标记表检查,未 Try 则 Cancel 直接返回成功
幂等Confirm/Cancel 因网络抖动被重试多次重复扣款、重复发货三个方法全部幂等(基于业务单号唯一键)
悬挂Confirm 先到达被拒绝(无 Try 记录),随后 Try 才到,业务逻辑被 Try 执行了,但事务已判定失败资源被占用但永远不释放在 Try 前检查事务状态表,已确认/已取消则拒绝 Try

失败处理完整链路(6 步)

1. 失败记录:写失败日志 + 更新事务状态表(FAILED)
2. 幂等重试:定时任务扫 FAILED → 基于业务单号幂等执行
3. 超时兜底:重试 N 次仍失败 → 标记 NEED_MANUAL
4. 告警通知:短信/钉钉/飞书通知值班
5. 对账巡检:日终对账兜底,发现不一致生成差错账
6. 人工介入:工程师查失败现场,手工补偿

超时回查机制

  • Seata TCC 框架会定期回查分支事务状态
  • 如果分支事务长时间未 Confirm,框架会主动询问:"你成功了吗?"
  • 业务方需要实现"状态查询接口"(如 queryConfirmStatus(txn_id))

对账系统的兜底作用

  • TCC 不是 100% 可靠的,极端情况下(如 TC 故障 + 业务方宕机)仍可能不一致
  • 对账系统是最后一道防线:日终/小时级扫描所有事务状态,发现不一致生成差错账
  • 大厂金融系统标配:TCC + 对账 + 人工兜底

工程最佳实践

  • 使用 Seata TCC 框架(自动处理空回滚/幂等/悬挂)
  • 自建 TCC 必须处理三大坑 + 超时回查 + 对账
  • 失败重试次数建议 3-5 次,间隔指数退避(1s → 2s → 4s)
  • 告警要分级:普通失败→钉钉,超时失败→电话/短信

STEP 4 · 简化

一句话总结:TCC 三大坑(空回滚/幂等/悬挂)必须同时处理;重试的前提是幂等,幂等的前提是三大坑都处理好;对账是终极兜底。

常见误区

"TCC 的 Confirm/Cancel 失败了,只要重试就行"
重试的前提是幂等,否则重试会重复扣款/重复发货
"TCC 只需要处理 Confirm/Cancel 失败"
TCC 有三大坑必须同时处理(空回滚/幂等/悬挂),不仅仅是失败重试
"TCC 是 100% 可靠的"
TCC 不是 100% 可靠,极端故障下需要对账系统兜底
"TCC 的三大坑是业务问题"
三大坑是工程实践问题,必须通过 Try 标记表/事务状态表/业务单号唯一键等技术手段解决
"Seata TCC 不需要业务方做任何事"
Seata 已自动处理三大坑,但业务方仍需实现状态查询接口(超时回查)

延伸追问

"TCC 的 Cancel 失败了,但是 Try 已经成功了,这时候业务数据处于什么状态?怎么恢复?"
要点:资源已被 Try 冻结但未 Cancel,状态悬挂。恢复:定时扫表查所有 Try 状态超过 T 的事务,强制 Cancel 并记录差错账
"Seata TCC 框架的'超时回查'是怎么工作的?业务方需要做什么?"
要点:TC 定时扫描未完成的分支事务,调用业务方的 queryConfirmStatus 接口;业务方要实现状态查询接口
"如果 TCC 框架都故障了,怎么兜底?"
要点:对账系统是终极兜底。日终对账对比所有事务的最终状态,发现不一致生成差错账,人工介入
"TCC 和 Seata AT 都号称'强一致',区别是什么?"
要点:AT 基于 undo log 自动回滚,对业务透明但需要全局锁;TCC 业务显式补偿,侵入高但锁粒度更细、可审计
"TCC 的 Confirm 成功了但网络不通,协调者认为失败发了 Cancel,怎么办?"
要点:Cancel 必须幂等(已 Confirm 则直接返回成功);靠事务状态表判断;对账系统兜底

速查表

维度内容
三方法Try 冻结 / Confirm 提交 / Cancel 补偿
三大坑空回滚 / 幂等 / 悬挂
解决方案Try 标记表 / 业务单号唯一键 / 事务状态表
失败处理 6 步记录→幂等重试→超时兜底→告警→对账→人工
超时回查TC 定期回查分支事务状态,业务方实现状态查询接口
对账兜底日终/小时级对账,发现不一致生成差错账
关键金句"重试的前提是幂等,幂等的前提是三大坑都处理好"

关联题目

  • ⚠️ 《TCC 中,Confirm 或者 Cancel 失败了怎么办?》— 2026-09-23 Round 2 Q6, ⭐⭐⭐, 只答"记录+重试+人工",漏三大坑和幂等
  • 关联知识

    重试的前提是幂等,幂等的前提是三大坑都处理好
    买房交定金(Try),确认合同(Confirm),过户(提交);出问题定金退还(Cancel)
    ✦ 记 忆 口 诀 ✦
    空回滚/幂等/悬挂三坑必须同时处理 / 对账是终极兜底
    关键可视化
    TCC 三方法语义
    flowchart LR
      A[转账场景] --> T[Try 冻结资源]
      A --> C[Confirm 确认提交]
      A --> X[Cancel 取消补偿]
      T --> T1[冻结 A 账户 100 元]
      C --> C1[真实扣款 100 元]
      X --> X1[释放冻结 100 元]
    TCC 三大坑
    flowchart TB
      A[TCC 三大坑] --> P1[空回滚]
      P1 --> P1D[Try 未执行但 Cancel 到达]
      P1D --> P1S[Try 标记表检查 未 Try 则 Cancel 直接成功]
      A --> P2[幂等]
      P2 --> P2D[Confirm 或 Cancel 重试]
      P2D --> P2S[三方法都基于业务单号做幂等]
      A --> P3[悬挂]
      P3 --> P3D[Confirm 先到被拒 Try 后到]
      P3D --> P3S[Try 前检查事务状态表 已确认或已取消则拒 Try]
    TCC 失败处理 6 步链路
    flowchart LR
      A[1 失败记录] --> B[写失败日志 + 更新事务状态表 FAILED]
      B --> C[2 幂等重试]
      C --> D[定时任务扫 FAILED + 基于业务单号幂等执行]
      D --> E[3 超时兜底]
      E --> F[重试 N 次仍失败 标记 NEED_MANUAL]
      F --> G[4 告警通知]
      G --> H[短信 钉钉 飞书通知值班]
      H --> I[5 对账巡检]
      I --> J[日终对账兜底 发现不一致生成差错账]
      J --> K[6 人工介入]
      K --> L[工程师查失败现场 手工补偿]
    对账系统兜底
    flowchart TB
      A[TCC 不是 100% 可靠] --> B[极端故障]
      B --> B1[TC 故障 + 业务方宕机]
      B --> C[对账系统是最后一道防线]
      C --> D[日终或小时级扫描所有事务状态]
      D --> E[发现不一致生成差错账]
      E --> F[人工处理]
      F --> G[大厂金融标配 TCC + 对账 + 人工兜底]
    知识关系

    ⬆️ 前置(Prerequisite)

    distributed-tx-overview

    🔄 延伸(Extends)

    cross-border-payment-design

    ⚡ 对比(Contrast)

    Seata AT— AT 低侵入框架自动回滚;TCC 高侵入业务显式补偿但锁粒度更细
    🎯 概念 📏 规则 ⚠️ 误区 🔍 追问 ✨ 口诀 共 0 张卡,点击翻面