dubbo教程-10-4-TCC分布式事务解决方案

写在前面

hello 大家好

欢迎大家收看御风大世界

本次课使我们DUBBO系列教程的第10课第4小结

本次课我们还是一起来讨论下分布式事务的解决方案

相较于上次课

我们讲到的

2PC 和 3PC 的 阶段性事务提交方案

我们本次的 TCC 分布式事务解决方案

有了一些提升

但是 在另外一些方面

却增加了 程序实现过程中的 耦合度

TCC 今天我们一起来探讨和学习下!

TCC是什么?

方案简介

TCC(Try-Confirm-Cancel)的概念,最早是由Pat Helland于2007年发表的一篇名为《Life beyond Distributed Transactions:an Apostate’s Opinion》的论文提出。

TCC是服务化的二阶段编程模型,其Try、Confirm、Cancel 3个方法均由业务编码实现;

Try操作作为一阶段,负责资源的检查和预留。

Confirm操作作为二阶段提交操作,执行真正的业务。

Cancel是预留资源的取消。

TCC事务的Try、Confirm、Cancel可以理解为SQL事务中的Lock、Commit、Rollback。

处理流程

为了方便理解,下面以电商下单为例进行方案解析,这里把整个过程简单分为扣减库存,订单创建2个步骤,库存服务和订单服务分别在不同的服务器节点上。

1、Try 阶段从执行阶段来看,与传统事务机制中业务逻辑相同。但从业务角度来看,却不一样。TCC机制中的Try仅是一个初步操作,它和后续的确认一起才能真正构成一个完整的业务逻辑,这个阶段主要完成:

完成所有业务检查( 一致性 )

预留必须业务资源( 准隔离性 )

Try 尝试执行业务 TCC事务机制以初步操作(Try)为中心的,确认操作(Confirm)和取消操作(Cancel)都是围绕初步操作(Try)而展开。因此,Try阶段中的操作,其保障性是最好的,即使失败,仍然有取消操作(Cancel)可以将其执行结果撤销。

假设商品库存为100,购买数量为2,这里检查和更新库存的同时,冻结用户购买数量的库存,同时创建订单,订单状态为待确认。

2、Confirm / Cancel 阶段根据Try阶段服务是否全部正常执行,继续执行确认操作(Confirm)或取消操作(Cancel)。 Confirm和Cancel操作满足幂等性,如果Confirm或Cancel操作执行失败,将会不断重试直到执行完成。

Confirm:当Try阶段服务全部正常执行, 执行确认业务逻辑操作

这里使用的资源一定是Try阶段预留的业务资源。在TCC事务机制中认为,如果在Try阶段能正常的预留资源,那Confirm一定能完整正确的提交。Confirm阶段也可以看成是对Try阶段的一个补充,Try+Confirm一起组成了一个完整的业务逻辑。

Cancel:当Try阶段存在服务执行失败, 进入Cancel阶段

Cancel取消执行,释放Try阶段预留的业务资源,上面的例子中,Cancel操作会把冻结的库存释放,并更新订单状态为取消。

方案总结

TCC事务机制相对于传统事务机制(X/Open XA),TCC事务机制相比于上面介绍的XA事务机制,有以下优点:

性能提升 具体业务来实现控制资源锁的粒度变小,不会锁定整个资源。

数据最终一致性 基于Confirm和Cancel的幂等性,保证事务最终完成确认或者取消,保证数据的一致性。

可靠性 解决了XA协议的协调者单点故障问题,由主业务方发起并控制整个业务活动,业务活动管理器也变成多点,引入集群。

缺点: TCC的Try、Confirm和Cancel操作功能要按具体业务来实现,业务耦合度较高,提高了开发成本。

TCC 框架

我找了很多 TCC框架 给大家介绍下我比较看上的一个框架

tcc-transaction

这个框架 大家可以在github下载看他的源码

https://github.com/ibywind/tcc-transaction

我们下节课也会针对于他的一些具体实现

做一次源码解读

他主要的一个思路是

把一个全局事务 存储在外部系统 (文件,数据库,zookeeper,redis等)

然后这个全局事务中,我们有 整个事务参与者的一个list列表

我们存储事务的时候 序列化,取出事务的时候反序列化

反序列化得到的 是 全局事务的一个对象 (还有里面的 事务参与者示例)

事务参与者实例 中存储了 这个分支事务 (子事务) 的 confirm方法和cancel方法

注意这里又要用到反射了

因为 存储的是 方法对象 (包含当时参数列表)

所以我们就可以 通过反射执行了

由于 tcc-transaction-core 这个项目 在所有的 事务参与者中 都有引入

所以反射 执行 相当于就是 本地执行

本地执行 的时候 操作的是 本地的事务 (比如说 通常我们一个模块 对应一个数据库)

我们看下 作者对于 全局事务 transaction 的抽象

接下来就是具体业务的时候配合框架的代码片段

我们一起来看下

大家看到了吗

以前的一个方法 变成了 三个方法了

try 阶段 我们 做一个 预状态

confirm 阶段我们 更新数据库为 目标逻辑状态

cancel 阶段我们 更新数据库为原始状态

好的这节课 我们就讲到这里

后续我们会一起来详细 分享下 源码解读的一些东西

大家也可以看下这个项目框架的源码

如果大家有什么新的体会

也可以跟我沟通哦

我们一起进步

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181219A15U2300?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券