TCC分布式事务

何为TCC?
Try-Confirm-Cancel,即补偿型事务TCC分布式事务的核心,先尝试改变数据库状态为中间态,如果没有问题才进行真正的修改,如果有问题则返回之前的状态,三个部分拆解如下:

  • Try:尝试将结果修改为中间态;
  • Confirm:如果Try成功,就真正将状态修改为已处理;
  • Cancel:如果Try失败,将中间态回滚至最初状态;

先来看看业务场景,假设你现在有一个电商系统,里面有一个支付订单的场景。那对一个订单支付之后,我们需要做下面的步骤:

  • 更改订单的状态为“已支付”
  • 扣减商品库存
  • 给会员增加积分
  • 创建销售出库单通知仓库发货

16e7a7d9ee4998e7cf0b69cb7345c94a.png

Try

那么在Try应该如何做?
首先,上面那个订单服务先把自己的状态修改为:OrderStatus.UPDATING。表示正在修改。
然后呢,库存服务直接提供的那个reduceStock()接口里,也别直接扣减库存啊,你可以是冻结掉库存。你可以把可销售的库存:100 - 2 = 98,设置为98没问题,然后在一个单独的冻结库存的字段里,设置一个2。也就是说,有2个库存是给冻结了。
积分服务的addCredit()接口也是同理,别直接给用户增加会员积分。你可以先在积分表里的一个预增加积分字段加入积分。
仓储服务的saleDelivery()接口也是同理啊,你可以先创建一个销售出库单,但是这个销售出库单的状态是“UNKNOWN”。

Confirm

为了感知各个阶段的执行情况并推进下一阶段的进程,通常需要相应的框架,如ByteTCC、himly、tcc-transaction等。
当框架感应到所有Try都成功了,就会进行Confirm,将Try阶段的中间态修改为最终状态。
如果这一阶段出现问题,要么不停重试(加上定时器)、要么重试一定次数失败并记录日志。

Cancel

这个时候,订单服务的TCC分布式事务框架只要感知到了任何一个服务的Try逻辑失败了,就会跟各个服务内的TCC分布式事务框架进行通信,然后调用各个服务的Cancel逻辑。