TCC实现指令原子性的原理
TCC(Try-Confirm-Cancel)通过三阶段操作实现业务层面分布式事务的原子性,其核心在于资源预留和状态管理的设计:
Try阶段(预留)
- 对涉及的所有业务操作预先检查并预留资源,例如锁定库存、冻结账户余额、生成临时订单等。此阶段不直接提交最终操作,而是确保后续Confirm或Cancel可执行。
- 每个子服务的Try操作独立执行,若全部成功则进入Confirm阶段;任一失败则触发Cancel阶段。
Confirm阶段(确认)
- 基于Try阶段预留的资源,执行最终业务操作(如扣减库存、实际扣款)。此时因资源已预留,操作必然成功。
- 需设计幂等性接口,防止网络重试导致重复提交。
Cancel阶段(撤销)
- 当Try阶段部分失败时,撤销已预留的资源(如释放库存、解冻金额)。同样需保证幂等性。
对比二阶段提交(2PC)
- 数据层:2PC在数据库层面通过Prepare/Commit实现,依赖数据库事务。
- 业务层:TCC将事务控制上移到业务代码,通过预留+确认/撤销的抽象模式,灵活适配异构系统。
实际应用关键点
幂等性设计
Confirm/Cancel可能因网络问题重试,需通过唯一事务ID或状态标记避免重复执行。资源预留方式
- 数据库操作:通过状态字段(如
status=TRY_RESERVED)标记预留状态,Confirm时更新为CONFIRMED。 - 外部服务调用:如机票预订场景,航空公司接口需提供预留、确认、撤销三个独立接口。
- 数据库操作:通过状态字段(如
超时与悬挂问题
需引入事务协调器记录状态,避免Try成功但因网络丢失导致长期未Confirm/Cancel的资源滞留。
开源实现参考
- Seata:支持TCC模式,提供全局事务协调框架。
- Hmily:轻量级TCC事务框架,适用于微服务场景。
示例场景解答(订票系统)
Try阶段
- 调用深圳航空接口预留深圳→上海机票(锁定座位,生成临时订单)。
- 调用上海航空接口预留上海→北京机票。
Confirm阶段
- 两段机票均预留成功时,分别调用确认接口完成实际出票。
Cancel阶段
- 若深圳航空预留失败,则调用上海航空的撤销接口释放预留座位。
通过这种设计,无论涉及多少服务,只要所有Try成功则最终确认,否则全部撤销,从而保证原子性。