连载中 4/18

TCC:把事务搬进业务代码

2026-06-15 · 1719 阅读 · 0 评论 · 0 赞

性能与侵入的交易

下单链路要跨订单、库存、账户三个服务,XA 一个数量级的吞吐折扣付不起,DBA 那句「用业务改造来换性能」就是出路:TCC(Try-Confirm-Cancel)——把 2PC 的两阶段从数据库层抬到业务层,锁不再由数据库行锁担任,改用业务字段自己表达。本篇先把模型立起来,三大坑留给下一篇。

三个接口各管一段

每个参与者从「一个接口」扩成「三个接口」:

Try:预留资源——不直接完成业务,而是把资源圈起来。账户服务 Try:校验余额充足,冻结 100 元(balance 不动,frozen 加 100);库存服务 Try:预占库存(可售减一,预占加一);订单服务 Try:生成「处理中」订单。

Confirm:确认提交——全部 Try 成功后逐个确认,用预留的资源真正完成业务:frozen 减 100(钱正式扣掉)、预占转真实扣减、订单状态改为已创建。Confirm 不允许再失败——它该做的检查和资源,Try 阶段已经都保证好了。

Cancel:取消释放——任一 Try 失败就逐个取消,把圈走的资源放回去:frozen 减 100、预占库存退回可售、订单标记关闭。

扣款一单的完整时序

Try    账户: 校验余额,frozen +100        (可提现余额不变)
Try    库存: 预占 +1,可售 -1
Try    订单: 生成「处理中」订单
  ↓ 全部成功
Confirm 账户: frozen -100(钱正式划走)
Confirm 库存: 预占 -1(转真实扣减)
Confirm 订单: 状态改为「已创建」
  ↓ 任一 Try 失败
Cancel  各方: 解冻、退预占、关订单

对照 2PC 看本质:Try 就是业务版的 prepare——都先把资源「握在手里」,但 2PC 握的是数据库行锁(锁着等全局指令),TCC 握的是业务字段里的冻结标记(不影响其他请求读余额、下别的单)。锁的粒度从「行」变成「该笔业务的部分资源」,阻塞消失,吞吐回来了。这就是业务改造换来的性能。

谁在当协调者

三阶段接口有了,谁来排时间表?事务管理器(框架层)负责:发起各参与者的 Try、收集结果、决定 Confirm 或 Cancel、处理超时、对失败的 Confirm/Cancel 持续重试。落地上可以用 Seata 的 TCC 模式(第 11 篇统一讲),也可以轻量自研——发起方一个状态表加定时任务,就是最朴素的协调者。纪律只有一条:Confirm 和 Cancel 必须设计成可重入——框架的重试没有任何一次保证只调一次,重试风暴是常态不是异常。

Try 的预留粒度怎么定

预留资源的形态因业务而异,老王总结了三种常见姿势:字段冻结(金额冻结、预占库存,最典型);状态占位(生成处理中订单、预创建记录);额度标记(外部系统额度预扣、券核销预占)。粒度设计的原则是 Try 要「够便宜、可释放」——预留本身不产生资损、不过期失效、Cancel 能一键还原。凡是 Try 里就开始真实扣减的,都是设计错了。

TCC 的得与失

维度2PC/XATCC
锁机制数据库行锁,全局阻塞业务冻结标记,无全局阻塞
吞吐低(掉一个数量级)高(接近本地事务)
业务侵入无(改配置)每个参与者三个接口
一致性强一致最终一致(Confirm 前可见冻结态)
开发成本高(含幂等、防悬挂全套纪律)

适用场景由此清晰:资源占用型、高并发、资金敏感的短事务——支付冻结、预占库存、额度预扣。长流程多环节的编排场景,TCC 三接口会膨胀成十几个,那是 Saga 的地盘(第 6 篇)。

小结

TCC 一句话:Try 预留、Confirm 确认、Cancel 释放,把 2PC 的锁从数据库行抬到业务字段,性能换侵入;Confirm 与 Cancel 天生要被重试,幂等纪律从写第一个接口起就要立。重试只是三大坑之一——空回滚、幂等、悬挂这三兄弟怎么防,下一篇逐个拆解。

503

10 年全栈工程师 · 503咖啡馆主理人

#分布式事务#TCC#Try-Confirm-Cancel#资源预留#最终一致

评论 (0)

相关推荐

连载中 12/20

排查四件套:jstack、jmap、jstat、jcmd 的实战分工

jstack 看线程在干什么,jmap 看堆里装了什么,jstat 看运行时在变什么,jcmd 是统一入口。四把刀各管一段,配合着用没有查不动的现场。

#jstack#jmap#jstat#jcmd#排查工具
2026-09-16 · 4 阅读 · 0 评论 · 0 赞
连载中 11/20

GC 日志:把回收过程翻译成人话

一行 GC 日志里塞着七种信息:谁触发的、收了哪、停了多久、活了哪些。加上 -Xlog 配置,再加上日志分析工具,GC 不再是只能盯监控曲线的黑盒。

#GC日志#Xlog#日志分析#GC监控#Full GC排查
2026-09-16 · 13 阅读 · 0 评论 · 0 赞
连载中 10/20

ZGC:亚毫秒停顿是怎么炼成的

百 G 大堆停顿不到一毫秒,靠的是把搬家全部挪到并发阶段——着色指针让引用自带状态,读屏障让搬运中的对象依然可访问。代价是吞吐与内存,收益是停顿与堆大小解耦。

#ZGC#着色指针#读屏障#亚毫秒停顿#分代ZGC
2026-09-15 · 8 阅读 · 0 评论 · 0 赞