当前位置:首页>排行榜>TCC 和 Saga 怎么选?面试常考的柔性事务

TCC 和 Saga 怎么选?面试常考的柔性事务

  • 更新时间 2026-11-02 07:42:57
TCC 和 Saga 怎么选?面试常考的柔性事务

被问到分布式事务怎么保一致,十个人有八个会说上 TCC 或者 Saga。再往下问:Cancel 比 Try 先到怎么办,Saga 补偿为什么要逆序,大多就卡壳了。我前几年面试也只背过定义,真到要落地才发现全是坑。

「TCC 的三段到底怎么串?」

TCC 把每个操作拆成 Try、Confirm、Cancel。Try 不真干事,只做资源检查和预留,比如冻结库存而不是扣减;Confirm 才真正提交预留;Cancel 把预留退回。关键在 Try 必须可补偿、可查询,Confirm 和 Cancel 都要幂等。而且 Try 阶段不能做真正提交,否则 Cancel 就退不回了,这是新手最容易踩的线。

// Seata TCC 模式:三段都是本地事务@TwoPhaseBusinessAction(name = "deduct", commitMethod = "confirm",                        rollbackMethod = "cancel")publicbooleantryDeduct(BusinessActionContext ctx, long skuId, int n) {return freeze(skuId, n);          // Try:冻结,不真扣}publicbooleanconfirm(BusinessActionContext ctx) {return deductReal(ctx);           // Confirm:真扣减}publicbooleancancel(BusinessActionContext ctx) {return unfreeze(ctx);             // Cancel:退回冻结}

「TCC 最坑的地方在哪?」

三个绕不开的异常:空回滚、悬挂、幂等。Cancel 因重试比 Try 先到,Try 还没执行就要能处理没东西可退;悬挂是说 Try 迟到、Cancel 已结束,这个 Try 必须识别出来直接丢弃;Confirm 和 Cancel 会被框架重试,所以必须幂等。我线上就因为漏了空回滚判断,冻结点被重复退回,账面凭空多了一笔。

「那 Saga 的正反向又是什么?」

Saga 不锁资源,把长事务拆成一串本地事务 T1 到 T2 到 T3,正向一路推进;任意一步失败,就逆序补偿 C3、C2、C1 把前面的操作回退。

// Saga:正向步骤 + 对应补偿,失败逆序回滚step("扣库存", this::deduct,    this::refundStock);step("创订单", this::create,    this::cancelOrder);step("发通知", this::notify,    this::undoNotify);// 第 2 步失败 → 执行 refundStock → cancelOrder

「你线上到底怎么选?」

短事务、要求强一致、像库存扣减这种高竞争场景,我选 TCC,代价是侵入业务、开发重。跨多服务、链路长、能接受最终一致的下单履约流程,我选 Saga,实现轻,但补偿逻辑要自己写对,隔离性差还得加语义锁。小事务本地事务加消息表就够了,别一上来就上这两个。比如下单要扣库存、优惠券、积分三个服务,用 Saga 一路补偿,比 TCC 少写两套预留接口;换成秒杀扣库存,TCC 的预留在前面就把超卖挡住,Saga 只能事后回滚,用户体验差一截。这段差别看着小,真到压测和故障演练就会放大。

三句话收尾:TCC 是三段式、强一致、开发重、怕空回滚;Saga 是正反向、最终一致、补偿难、隔离弱;选型看一致性要求、链路长度、是不是高竞争,没有哪个能包打天下。

随机文章