分布式事务之TCC
业务场景介绍
假设现在有一个电商系统,里面有一个支付订单的场景。
对一个订单进行支付之后,我们需要做下面的步骤:
- 更改订单的状态为“已支付”
- 扣减商品库存
- 给会员增加积分
- 创建销售出库单通知仓库发货
以上业务场景对应下面的代码:
public class OrderService {
// 库存服务
@Autowired
private InventoryService inventoryService;
// 积分服务
@Autowired
private CreditService creditService;
// 仓储服务
@Autowired
private WmsService wmsService;
// 对这个订单完成支付
public void pay(){
//对本地的的订单数据库修改订单状态为"已支付"
orderDAO.updateStatus(OrderStatus.PAYED);
//调用库存服务扣减库存
inventoryService.reduceStock();
//调用积分服务增加积分
creditService.addCredit();
//调用仓储服务通知发货
wmsService.saleDelivery();
}
}
补偿事务:TCC
TCC是Try-Confirm-Cancel的简称:
Try 阶段:尝试执行,完成所有业务检查(一致性),预留必需业务资源(准隔离性)。
Confirm 阶段:确认真正执行业务,不作任何业务检查,只使用 Try 阶段预留的业务资源,Confirm 操作满足幂等性。要求具备幂等设计,Confirm 失败后需要进行重试。
Cancel 阶段:取消执行,释放 Try 阶段预留的业务资源,Cancel 操作满足幂等性。Cancel 阶段的异常和 Confirm 阶段异常处理方案基本上一致。
Try阶段
Confirm阶段
Cancle阶段
总结与思考
总结一下,你要玩 TCC 分布式事务的话:首先需要选择某种 TCC 分布式事务框架,各个服务里就会有这个 TCC 分布式事务框架在运行。
然后原本的一个接口,要改造为 3 个逻辑,Try-Confirm-Cancel:
- 先是服务调用链路依次执行 Try 逻辑。
- 如果都正常的话,TCC 分布式事务框架推进执行 Confirm 逻辑,完成整个事务。
- 如果某个服务的 Try 逻辑有问题,TCC 分布式事务框架感知到之后就会推进执行各个服务的 Cancel 逻辑,撤销之前执行的各种操作。
问题1:如果有一些意外的情况发生了,比如说订单服务突然挂了,然后再次重启,TCC 分布式事务框架是如何保证之前没执行完的分布式事务继续执行的呢?
所以,TCC 事务框架都是要记录一些分布式事务的活动日志的,可以在磁盘上的日志文件里记录,也可以在数据库里记录。保存下来分布式事务运行的各个阶段和状态。
问题2:万一某个服务的 Cancel 或者 Confirm 逻辑执行一直失败怎么办呢?
TCC 事务框架会通过活动日志记录各个服务的状态。举个例子,比如发现某个服务的 Cancel 或者 Confirm 一直没成功,会不停的重试调用它的 Cancel 或者 Confirm 逻辑,务必要它成功!
给大家推荐几个比较不错的框架,都是国内开源的:ByteTCC,TCC-transaction,Himly。
大家有兴趣的可以去它们的 GitHub 地址,学习一下如何使用,以及如何跟 Spring Cloud、Dubbo 等服务框架整合使用。
还没有评论,来说两句吧...