TCC(Try - Confirm - Cancel)。
**
业务场景
电商系统 — 支付订单场景
订单支付 —> 更改订单的状态为【已支付】 —> 扣减商品库存 —> 给会员增加积分 —> 创建销售出单通知仓库发货。
上述的步骤,要么一起成功,要么就必须一起失败。必须是一个整体性的事务。
要不然,如果订单的状态都修改为【已支付】了,结果库存服务扣减库存失败。那么库存服务操作数据库里的库存数量的数据就是有误的。
整体流程不是整体事务导致的问题图例
所以,整体的流程,要么全部成功,如果任何一个服务的操作失败了,就全部一起回滚,撤销已经完成的操作。
比如说库存服务要是扣钱库存失败了,那么订单服务就得撤销那个修改订单状态的操作,然后得停止执行增加积分和通知出库的两个操作。
整体流程应具备整体事务图例
**
落地实现TCC分布式事务
TCC实现阶段一:Try
在这个阶段里面,支付订单成功的话,先将订单服务的状态修改为 OrderSatus.Updating
。
然后,针对库存服务直接提供一个 reduceStock()
接口里,也别直接扣减库存,而是去冻结库存。
比如原本库存数量是100个,购买了2个,那就别直接扣减库存100-2=98个,而是单独在一个冻结库存的字段里,设置为2,代表有2个库存被冻结了。
积分服务里的 addCredit()
接口也是同理,别直接给用户增加会员积分。可以现在积分表里的一个预增加积分字段里加入积分。
比如,用户原本积分是1190,现在增加10个积分,别直接1190+10=1200积分,而是保持积分为1190不变,在一个预增加字段里,比如 prepare_add_credit
字段里,设置一个10,表示有10个积分准备增加。
仓储服务的 saleDelvery()
接口也是同理,可以先创建一个销售出库但,但是这个销售出库单的状态是 UNKNOWN
(代表刚刚创建的销售出库单,此时还不确认它的状态是什么)。
以上对各个服务的操作过程,就是TCC分布式事务里的Try阶段。
总结上来说,如果要实现一个TCC分布式事务,手续爱你你的业务的主流程以及各个接口提供的业务含义,不能是直接完成那个业务的操作,而是要有一个中间的状态,完成一个Try的操作。
Try操作的整体流程图例
**