分布式事务之TCC事务模型

正文

咱们先套一个业务场景进去,以下图所示 面试

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

概念

TCC的全称是(Try-Confirm-Cancel)。以下图所示编程

ps:TCC又能够被称为两阶段补偿事务,第一阶段try只是预留资源,第二阶段要明确的告诉服务提供者,这个资源你到底要不要,对应第二阶段的confirm/cancel,用来清除第一阶段的影响,因此叫补偿型事务。bash

再打个比方,说TCC过高大上是吧,讲RM中的prepare、commit、rollback接口,总知道吧。能够类比的这么理解 架构

那差异在哪呢? rollback、commit、prepare,站在开发者层面是感知不到的,数据库帮你作了资源的操做! 而try、confirm、cancel,站在开发者层面是能感知到的,这三个方法的业务逻辑,即对资源的操做,开发者是要本身去实现的! 好,下面套入咱们的场景,怎么作呢。好比,你的订单服务中原本只有一个接口框架

//修改代码状态
orderClient.updateStatus();
复制代码

都要拆为三个接口,即分布式

orderClient.tryUpateStatus();
orderClient.confirmUpateStatus();
orderClient.cancelUpateStatus();
复制代码

注意了:面试官若是问你,TCC有什么缺点?这就是很严重的缺点,**对代码入侵性大!**每套业务逻辑、都要按try(请求资源)、confirm(操做资源)、cancel(取消资源),拆分为三个接口!spa

具体每一个阶段,每一个服务业务逻辑是什么样的呢? 假设,库存数量原本是50,那么可销售库存也是50。帐户余额为50,可用余额也为50。用户下单,买了1个单价为1元的商品。流程以下: Try阶段 订单服务:修改订单的状态为支付中 帐户服务:帐户余额不变,可用余额减1,而后将1这个数字冻结在一个单独的字段里 库存服务:库存数量不变,可销售库存减1,而后将1这个数字冻结在一个单独的字段里 confirm阶段 订单服务:修改订单的状态为支付完成 帐户服务:帐户余额变为(当前值减冻结字段的值),可用余额不变(Try阶段减过了),冻结字段清0。 库存服务:库存变为(当前值减冻结字段的值),可销售库存不变(Try阶段减过了),冻结字段清0。 cancel阶段 订单服务:修改订单的状态为未支付 帐户服务:帐户余额不变,可用余额变为(当前值加冻结字段的值),冻结字段清0。 库存服务:库存不变,可销售库存变为(当前值加冻结字段的值),冻结字段清0。线程

伪代码

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

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

注意了,这种写法其实严格上来讲,不是不行。看你业务场景,由于存在一些瑕疵,看你本身有没办法接受 (1)cancel或者confirm出现异常了,你怎么处理? 例如在cancel阶段执行以下三行代码

orderClient.cancelUpdateStatus();
accountClient.cancelDecrease();
repositoryClient.cancelDecrease();
复制代码

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

try{
    xxclient.try();
}catch(Throwable t){
    xxclient.cancel();
    throw t;
}
xxclient.confirm();
复制代码

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

所以,须要引入TCC分布式事务框架,事务的Try、Confirm、Cancel三个状态交给框架来感知!你只要告诉框架,Try要执行啥,Confirm要执行啥,Cancel要执行啥!若是Cancel过程出现异常了,框架有内部的补偿措施给你恢复数据! 以分布式tcc框架hmily为例,若是出现cancel异常或者confirm异常的状况,在try阶段会保存好日志,Hmily有内置的调度线程池来进行恢复,不用担忧。 那hmily,怎么感知状态的呢?也很简单,就是切面编程,核心逻辑以下几行

咱们在使用过程当中,只要经过@Tcc注解告诉框架confirm方法执行啥,cancel方法执行啥便可!其余的交给框架帮你处理! 好了,很少说了,再说下去就是hmily源码解析了,你们有空本身去了解!

挖坑

那若是碰到,不一样平台之间调用,你要怎么保证事务?好比,个人服务要调银行接口,你以为可能让银行接你的tcc框架么?或者让银行接你的消息对列?大家以为现实么?固然,有的人会说:"一个http直接调了。"嗯,少年有想法! ok,那么业内针对这种涉及到第三方接口的服务调用,如何保证一致性?你们好好思考。

相关文章
相关标签/搜索