分布式事务解决方案-基于TCC分布式事务的简述

前言

之前一篇文章分布式事务解决方案-基于XA协议的两阶段提交2PC简述,说过事务的定义和分布式事务的定义,也讲述过分布式事务引发的各种问题。上篇文章对分布式事务出现的“一致性”问题,使用的是XA/2PC模式,但因为这种方法使用起来局限性特别大,本章咱们在;提出一种解决方案:叫做TCC分布式事务解决方案。

TCC介绍

关于TCC(Try-Confirm-Cancel)的概念,最早是由Pat Helland于2007年发表的一篇名为《Life beyond Distributed Transactions:an Apostate’s Opinion》的论文提出。在该论文中,TCC还是以Tentative-Confirmation-Cancellation作为名称;正式以Try-Confirm-Cancel作为名称的,可能是Atomikos(Gregor Hohpe所著书籍《Enterprise Integration Patterns》中收录了关于TCC的介绍,提到了Atomikos的Try-Confirm-Cancel,并认为二者是相似的概念)。

TCC事务机制相对于传统事务机制(X/Open XA),其特征在于它不依赖资源管理器(RM)对XA的支持,而是通过对(由业务系统提供的)业务逻辑的调度来实现分布式事务。对于业务系统中一个特定的“业务逻辑方”(如:积分服务,库存服务),其对外提供服务时,必须接受一些不确定性,即对业务逻辑执行的一次调用仅是一个临时性操作,调用它的“消费方”(如上游的应用)保留了后续的取消权。如果“消费方”认为全局事务应该rollback,它会要求取消之前的临时性操作,这就对应“业务逻辑方”的一个取消操作。而当上游应用认为全局事务应该commit时,它会放弃之前临时性操作的取消权,这对应“业务逻辑方”的一个确认操作。 每一个初步操作,最终都会被确认或取消。因此,针对一个具体的业务服务,TCC事务机制需要业务系统提供三段业务逻辑:初步操作Try、确认操作Confirm、取消操作Cancel。

从上描述咱们可以知道,TCC事务其实主要包含两个阶段:Try、Confirm/Cancel阶段。上游应用如果需要控制这两个阶段,那么“业务逻辑方”的服务就必须提供对外的try/confirm/cancel接口操作。

1、 try-尝试执行业务

a、完成所有业务检查(一致性)
b、预留必须业务资源(准隔离性)

2、confirm-确认执行业务

a、真正执行业务、不需要在作任何业务检查
b、只使用Try阶段预留的业务资源
c、必须保证操作的幂等性

3、cancel-取消执行业务

a、释放Try阶段预留的业务资源
b、Cancel操作必须保证幂等性

场景

“下单操作”与“库存变动”,两个事务,咱们要求他们具备一致性,就是说必须满足这种情况:“下单成功,库存必须修改成功“ 或 ”订单不成功,库存也不变”。

描述:有100个商品,有人下单买走1个,我们要同事进行订单服务和库存服务操作。要么“下单成功,库存必须修改成功“ 要么 ”订单不成功,库存也不变”。

 业务分析

为了保证tcc事务顺利完成,咱们队订单进行状态划分:updating状态表示,订单准备完毕,验证完毕。confirm状态:表示订单提交完毕。cancel状态:订单取消完毕。整个流程应用引入“TCC事务中间件”进行对两个事务监听执行状态以及结果。(注:具体状态叫什么,随便起名,爱叫什么都行。)

1、try阶段

a、先对库存加锁,不要让其他订单干扰库存值。

b、上游应用对订单服务和库存服务进行try操作,修改订单到中间状态updating,库存改为99、预留库存为1,两个分支事务全部成功,就进行confirm操作。

c、释放库存锁,不要耽误别的客户下单。如果这订单和库存两个事务,任何一个失败,都表示整个所有事务失败,进行cancel操作。

2、如果上面的try阶段操作成功,则进行confirm阶段

修改订单状态为confirm,修改预留库存为0.这就表示订单结束了。

3、如果try阶段失败,则进行cancel操作

 

a、库存先加锁。

b、修改订单状态为cancel,修改库存为100(原库存+预留库存),表示整体事务失败。

c、库存解锁。

极限分析

以上基本能保证99.99..%的成功率,为什么不是100%?

除却各种不可抗拒因素外,其实仔细分析,在tcc逻辑中,try失败了有cancel做后备保证,但是假如cancel/confirm操作失败了,怎么办?解决方案咱们在上面几张图片中已经体现了,每个操作都有“操作日志”,具体你如何处理这些操作日志,你是“定时检查操作日志”,“最大次数提交”,还是“手动通知人工处理”,这些都是可行的办法,最终如何处理还要根据你的具体业务进行处理。

常用TCC事务组件

ByteTCC,TCC-transaction,Himly。这些都是java方面的框架(java生态确实好,每样框架组件你都至少能找到3个以上的可选方案),虽然自己实现一个基本功能TCC监听框架不是很复杂,但是这些框架功能更多,更稳定和更放心。.net/core方面找了好久,发现DeepTransactionCore或DeepTransaction还可以(功能很单纯:只有监听和事务排序。),可以在nuget上面进行安装(示例:《事务管理组件deeptransactioncore的应用》)。

优缺点分析

1、 TCC的主要优点有

a、因为Try阶段检查并"预留了资源"(TCC的核心),所以confirm阶段一般都可以执行成功。

b、业务严谨,各个阶段都有保障,具有较强的事务“一致性”。

2、 TCC的主要缺点有

a、因为事务状态管理,将产生多次DB操作,这将损耗一定的性能,并使得整个TCC事务时间拉长。

b、事务涉及方越多,Try、Confirm、Cancel中的代码就越复杂,可复用性就越底(这一点主要是相对最终一致性方案而言的)。另外涉及方越多,这几个阶段的处理时间越长,失败的可能性也越高。

 

评论 (1) -

  • 想问一下,TCC、SAGA、以及本地消息表或基于事务消息的几中分布式事务各自适用的环境是什么?

添加评论

Loading