TCC(Try-Confirm-Cancel)事务补偿机制
一、TCC基本概念
TCC(Try-Confirm-Cancel)是一种业务层面的分布式事务解决方案,通过将业务操作拆分为三个阶段来实现最终一致性。
与2PC/3PC等资源层协议不同,TCC需要业务代码显式实现各阶段逻辑
二、核心设计思想
TCC的核心思想是"预留资源+最终确认"
TCC分为两步骤,分别如下:
-
第一步:Try(尝试),主要是对业务系统做检测及资源预留 (加锁,锁住资源)
-
第二步:根据 Try 的结果,决定是执行confirm 还是 cancel
1、Confirm(确认):执行真正的业务(执行业务,释放锁)
2、Cancle(取消):是预留资源的取消(出问题,释放锁)
三、3个核心阶段
为了方便理解,下面以电商下单为例进行方案解析,这里把整个过程简单分为扣减库存,订单创建 2 个步骤,库存服务和订单服务分别在不同的服务器节点上。
假设商品库存为 100,购买数量为 2,这里检查和更新库存的同时,冻结用户购买数量的库存,同时创建订单,订单状态为待确认。
1、Try阶段(尝试阶段)
-
目的:预留业务资源,完成所有业务检查
-
操作:
-
冻结部分库存(电商)
-
生成预订单(订单系统)
-
-
特点:
-
所有操作必须幂等
-
不产生最终业务结果
-
需要记录事务日志
-
2、Confirm阶段(确认阶段)
-
目的:确认执行业务,使用Try阶段预留的资源
-
操作:
-
扣减冻结的库存
-
确认订单生效
-
-
特点:
-
必须保证成功(不断重试直到成功)
-
操作必须幂等
-
不进行业务检查(已在Try阶段完成)
-
根据 Try 阶段服务是否全部正常执行,继续执行确认操作(Confirm)或 取消操作(Cancel)
Confirm 和 Cancel 操作满足幂等性,如果 Confirm 或 Cancel 操作执行失败,将会不断重试直到执行完成。
Confirm:当 Try 阶段服务全部正常执行, 执行确认业务逻辑操作,业务如下图:
这里使用的资源一定是 Try 阶段预留的业务资源。在 TCC 事务机制中认为,如果在 Try 阶段能正常的预留资源,那 Confirm 一定能完整正确的提交。
Confirm 阶段也可以看成是对 Try 阶段的一个补充, Try+Confirm 一起组成了一个完整的业务逻辑。
3、Cancel阶段(取消阶段)
-
目的:取消Try阶段预留的资源
-
操作:
-
释放冻结的库存
-
取消预订单
-
-
特点:
-
必须保证成功(不断重试直到成功)
-
操作必须幂等
-
需要处理Try阶段可能部分成功的情况
-
Cancel:当 Try 阶段存在服务执行失败, 进入 Cancel 阶段,业务如下图:
Cancel 取消执行,释放 Try 阶段预留的业务资源,上面的例子中,Cancel 操作会把冻结的库存释放,并更新订单状态为取消
四、最终一致性保证
-
TCC 事务机制以初步操作(Try)为中心的,确认操作(Confirm)和取消操作(Cancel)都是围绕初步操作(Try)而展开。因此,Try 阶段中的操作,其保障性是最好的,即使失败,仍然有取消操作(Cancel)可以将其执行结果撤销。
-
Try阶段执行成功并开始执行 Confirm阶段时,默认 Confirm阶段是不会出错的。也就是说只要Try成功,Confirm一定成功(TCC设计之初的定义) 。
-
Confirm与Cancel如果失败,由TCC框架进行重试补偿
-
存在极低概率在CC环节彻底失败,则需要定时任务或人工介入
五、TCC工作流程
异常情况:
-
任一Try失败:立即执行Cancel
-
Confirm 或 Cancel失败:不断重试
六、TCC的六大核心特性
1、业务侵入性:需要业务代码显式实现三个接口
2、最终一致性:通过重试机制保证最终一致
3、隔离性:通过资源预留防止脏读
4、幂等控制:每个阶段操作必须支持重复执行
5、空回滚:处理Try超时但实际成功的情况
6、防悬挂:防止Cancel比Try先到达
七、关键问题与解决方案
1、空回滚问题
场景:
-
Try未执行(网络超时)
-
但协调者触发了Cancel
解决方案:
-
在Try阶段记录事务日志
-
Cancel时检查是否有对应Try记录
-
无记录时执行空回滚并记录
2、幂等控制
场景:
- 网络重发导致重复调用
解决方案:
-
每个事务使用唯一事务ID
-
记录每个事务ID的执行状态
-
重复请求直接返回之前的结果
3、防悬挂问题
场景:
-
Try因网络拥堵延迟到达
-
Cancel先执行完毕
-
然后Try才到达
解决方案:
-
Cancel时记录已取消状态
-
Try执行前检查是否已被取消
八、典型应用场景
1、电商下单:
-
Try:冻结库存、预扣优惠券
-
Confirm:实际扣减
-
Cancel:释放资源
2、跨行转账:
-
Try:A行冻结金额,B行预增余额
-
Confirm:双方实际记账
-
Cancel:双方撤销操作
3、酒店预订:
-
Try:预留房间
-
Confirm:确认入住
-
Cancel:取消预订
实现模式
1、编码实现(业务耦合)
2、框架支持(推荐)
-
Seata(阿里开源)
-
ByteTCC
-
Himly
-
TCC-transaction