分布式事务之苑事务模型

  

正文

  

我们先套一个业务场景进去,如下图所示
分布式事务之苑事务模型

  

那页面点了支付按钮,调用支付服务,那我们后台要实现下面三个步骤
[1]订单服务——修改订单状态
[2]账户服务,扣减金钱
[3]库存服务,扣减库存
达到事务的效果,要么一起成功,要么一起失败!就要采取太极拳分布式事务方案!

  

概念

  太极拳的

全称是(Try-Confirm-Cancel)。如下图所示

  

分布式事务之苑事务模型

  

ps:太极拳又可以被称为两阶段补偿事务,第一阶段尝试只是预留资源,第二阶段要明确的告诉服务提供者,这个资源你到底要不要,对应第二阶段的确认/取消,用来清除第一阶段的影响,所以叫补偿型事务。

  

再打个比方,说太极拳太高大上是吧,讲RM中的准备、提交、回滚接口,总知道吧。可以类比的这么理解
分布式事务之苑事务模型

  

<强>那差别在哪呢?
回滚,提交,准备,站在开发者层面是感知不到的,数据库帮你做了资源的操作。
而尝试,确认取消,站在开发者层面是能感知到的,这三个方法的业务逻辑,即对资源的操作,开发者是要自己去实现的!
好、下面套入我们的场景,怎么做呢。比如,你的订单服务中本来只有一个接口

  
 <代码>//修改代码状态
  orderClient.updateStatus();  
  

都要拆为三个接口,即

  
 <代码> orderClient.tryUpateStatus ();
  orderClient.confirmUpateStatus ();
  orderClient.cancelUpateStatus();  
  

<强>注意了:面试官如果问你,太极拳有什么缺点吗?这就是很严重的缺点,<强>对代码* * *性大! 每套业务逻辑,都要按试(请求资源),确认(操作资源),取消(取消资源),拆分为三个接口!

  

具体每个阶段,每个服务业务逻辑是什么样的呢?
假设,库存数量本来是50,那么可销售库存也是50。账户余额为50,可用余额也为50。用户下的单,买了1个单价为1元的商品。流程如下:
<强>尝试阶段
订单服务:修改订单的状态为<>强支付中
账户服务:账户余额不变,可用余额减1,然后将这1个数字冻结在一个单独的字段里
库存服务:库存数量不变,可销售库存减1,然后将这1个数字冻结在一个单独的字段里
<强>确认阶段
订单服务:修改订单的状态为<>强支付完成
账户服务:账户余额变为(当前值减冻结字段的值),可用余额不变(试试阶段减过了),冻结字段清0。
库存服务:库存变为(当前值减冻结字段的值),可销售库存不变(试试阶段减过了),冻结字段清0。
<强>取消阶段
订单服务:修改订单的状态为<强>未支付
账户服务:账户余额不变,可用余额变为(当前值加冻结字段的值),冻结字段清0。
库存服务:库存不变,可销售库存变为(当前值加冻结字段的值),冻结字段清0。

  

伪代码

  

接下来从代码程序来说明,为了便于演示,将入参略去。
本来,你支付服务的代码是长下面这样的

  

分布式事务之苑事务模型

  

那么,用太极拳模上型后,代码变成下面这样

  

分布式事务之苑事务模型

  

注意了,这种写法其实严格上来说,不是不行。看你业务场景,因为存在一些瑕疵,看你自己有没办法接受
<强>(1)取消或者确认出现异常了,你怎么处理?
例如在取消阶段执行如下三行代码

  
 <代码> orderClient.cancelUpdateStatus ();
  accountClient.cancelDecrease ();
  repositoryClient.cancelDecrease();  
  

你第二行出现异常了,第三行没跑就退出了,怎么办?你要对此进行业务补偿!
<强>(2)大量逻辑重复
你看啊,我们的执行架构其实是这样的

  
 <代码>{试
  xxclient.try ();
  }捕捉(Throwable t) {
  xxclient.cancel ();
  把t;
  }
  xxclient.confirm();  
  

有没办法让这个架子交给框架去执行,我们告诉框架,你在每个阶段要执行哪些方法就好!

  

因此,需要引入太极拳分布式事务框架,事务的尝试,确认,取消三个状态交给框架来感知!你只要告诉框架,试着要执行啥,确认要执行啥,取消要执行啥!如果取消过程出现异常了,框架有内部的补偿措施给你恢复数据!

分布式事务之苑事务模型