← 每日面试题 学习看板

TCC中,Confirm或者Cancel失败了怎么办?

面试题/02架构设计题/02分布式/02分布式事务/TCC中,Confirm或者Cancel失败了怎么办?.md

完整讲解(权威版)

最后更新:2026-10-24 · 基于第 2 次作答

第一部分:知识重点剖析

核心考点定位:考察对 TCC 框架"失败处理机制"的完整认知——不止"重试+人工",还要覆盖幂等、空回滚、悬挂三大坑。

知识点拆解:

  1. 失败处理的完整链路(6 步)
   1. 失败记录:写失败日志 + 更新事务状态表(FAILED)
   2. 幂等重试:定时任务扫 FAILED → 基于业务单号幂等执行
   3. 超时兜底:重试 N 次仍失败 → 标记 NEED_MANUAL
   4. 告警通知:短信/钉钉/飞书通知值班
   5. 对账巡检:日终对账系统兜底,发现不一致生成差错账
   6. 人工介入:工程师查失败现场,手工补偿
  1. 幂等性是重试的前提(最关键)
  1. TCC 三大坑(必须同时处理)
坑触发条件表现解决
空回滚Try 未执行,Cancel 到达Cancel 操作不存在的资源Try 标记表检查,未 Try 则 Cancel 直接成功
幂等Confirm/Cancel 重试重复扣款/发货三方法都基于业务单号做幂等
悬挂Confirm 先到被拒,Try 后到资源被 Try 占用但事务已判失败Try 前检查事务状态,已确认/已取消则拒 Try
  1. 超时回查机制
  1. 对账系统的兜底作用
  1. 工程最佳实践

第二部分:考察方向与延伸递进

考察方向:

延伸递进面试题:

  1. "TCC 的 Cancel 失败了,但是 Try 已经成功了,这时候业务数据处于什么状态?怎么恢复?"
  1. "Seata TCC 框架的'超时回查'是怎么工作的?业务方需要做什么?"
  1. "如果 TCC 框架都故障了,怎么兜底?"

第三部分:面试者参考回答(300-600 字口语化)

面试官您好,TCC 的 Confirm 或 Cancel 失败处理,我一般按"自动恢复 + 人工兜底"两条链路设计。 自动恢复链路分三步: 1. 失败记录:把失败现场写到事务状态表,状态标记为 FAILED,记录失败原因、尝试次数 2. 幂等重试:定时任务扫描 FAILED 状态的事务,调用 Confirm/Cancel 重试。但这里有个关键点——Confirm 和 Cancel 必须幂等,因为重试会多次执行,如果不幂等就会重复扣款、重复发货。实现方式是基于业务单号建唯一键,重复请求直接返回上次结果 3. 超时兜底:重试 3-5 次仍失败,标记为 NEED_MANUAL,进入告警链路 人工兜底链路分三步: 1. 告警通知:通过短信/钉钉/飞书通知值班工程师 2. 对账巡检:日终对账系统扫描所有事务状态,发现不一致生成差错账,这是最后一道防线 3. 人工介入:工程师查失败日志、事务状态表、资源状态,手工补偿 这里还有个关键——TCC 有三大坑必须同时处理: - 空回滚:Try 因网络问题从未执行,但 Cancel 因协调者崩溃恢复而到达。解决:在 Try 标记表检查,未 Try 则 Cancel 直接返回成功 - 幂等:Confirm/Cancel 重试。解决:三个方法都必须基于业务单号做幂等 - 悬挂:Confirm 先到达被拒绝(无 Try 记录),随后 Try 才到,资源被 Try 占用但事务已判失败。解决:在 Try 前检查事务状态表,已确认/已取消则拒绝 Try Seata TCC 框架已经自动处理了这三大坑,但业务自建 TCC 一定要自己处理。另外,Seata 还有"超时回查"机制——TC 会定期回查分支事务状态,业务方需要实现一个状态查询接口,告诉 TC "我到底成功了没有"。 工程最佳实践:Confirm/Cancel 失败重试建议 3-5 次,间隔指数退避(1s → 2s → 4s);告警要分级,普通失败走钉钉,超时失败走电话/短信;对账系统是终极兜底,TCC 不是 100% 可靠,极端故障下靠对账发现不一致。 总结一句话:重试的前提是幂等,幂等的前提是三大坑都处理好,三大坑处理好的前提是业务方愿意投入。这也是为什么核心业务往往用 Seata TCC 而不是自建 TCC。

作答历史

#日期评分本轮主要问题记录
12026-09-233/5- ❌ 未提到 幂等性(idempotency)——这是重试的**前提条第 1 次
22026-10-234/5- 未提 TCC 三大坑中的空回滚与悬挂,只覆盖了幂等第 2 次

面试记录 2026-09-23(第 1 次)

题目:TCC 中,Confirm 或者 Cancel 失败了怎么办?

难度:medium

评分:⭐⭐⭐☆☆

我的回答

PEC 的提交或者回滚如果失败了,主流程第一个应该是记录,把这个事情整个记录下来,然后进行尝试,尝试重试,如果还是不行的话,就进行人工告警,消息告警,告警到人工去进行记录处理、接入处理。

点评

评分:⭐⭐⭐☆☆

优点:

不足:

补充:

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

面试记录 2026-10-23(第 2 次)

题目:TCC 中 Confirm 或 Cancel 失败了怎么办?

难度:medium

标签:arch/distributed/transaction, distributed/tcc

评分:⭐⭐⭐⭐☆(4/5)

练习次数:2

我的回答

tcc中如果前置都执行成功了,开始confirm了,但是执行时失败了,核心先做重试,规定做一定次数的重试,可以做扩散式重试,每次增加重试间隔,并且在重试到指定次数后,执行告警或者记录,通知人工介入,因为已经进入到confirm阶段就不能再去cancel回滚了,可以做脏状态,等待人工介入处理排查问题

而cancel执行失败也是类似的思路,已经失败要释放资源了,如果执行失败,则先进行扩散式的重试,并每次增加时间间隔,规避网络问题之类临时问题,如果达到指定次数还是无法执行成功,那么就要人工介入了

这些重试在前置都要做好幂等,不能因为执行多次而产生额外影响,可以通过类似状态机的机制,只能从a状态执行到b状态,如果已经是b状态则不执行

点评

评分:⭐⭐⭐⭐☆(4/5)

优点:

不足:

补充:

完整讲解见上方「完整讲解(权威版)」