需求: Dubbo 如何做分布式事务?? 除了fescar 那么高深的框架,今天来学习一下 tcc-transaction, github 上的star 有3000多个(https://github.com/changmingxie/tcc-transaction.git)。
介绍:
(1). tcc 指的是 try, cancel, confirm, 在 tcc-transaction 的源码中, cancel 和confirm 没有做幂等性控制,?需要程序员手动的保证他们的幂等性。?
(2). tcc-transaction 主要是通过补偿性的措施来保证分布式事务的。通过注解Compensable, 指定confirmMethod 和?cancelMethod 的名字。
(3). tcc-transaction 对dubbo 的支持,是通过重新 扩展 proxyFactory 的 spi,实现了Tccjavassist 和 tccjdk 方式来重新生成带有?Compensable 注解的 代理类。 原声的dubbo proxyFactory 是不能够生成带有?Compensable 注解的 代理类的。
(4).tcc-transaction 主要是通过spring 的 AOP 中 通知环绕的方式,来处理?Compensable 注解。
(5) 源代码中?CompensableTransactionAspect (先执行)和?ResourceCoordinatorInterceptor (后执行) 是两个 切面,执行的顺序依靠 spring core 中的 order 的大小, 越小 执行的顺序越是提前,CompensableTransactionAspect 的执行 order 是?Ordered.HIGHEST_PRECEDENCE。
(6) 通过AOP的环绕通知,我们知道 类 中CompensableTransactionInterceptor 调用?pjp.proceed() 不会执行 目标 method, 反而会执行?ResourceCoordinatorInterceptor 中的?interceptTransactionContextMethod方法,ResourceCoordinatorInterceptor 中的?pjp.proceed(pjp.getArgs())方法,才会调用执行目标方法。
好了, 首先得弄清楚tcc-transaction 给我们提供的案例,大家先倒入sql,比较全的那个sql 文档,含有is_deleted 字段,然后用tomcat 启动是完全可以执行的,同时我尝试的springboot start dubbo 版本也会放到github 上的,大家可以尝试用我的案例 结合springboot dubbo 应用去更好的解决分布式事务问题。
(7)个人觉得 tcc-transaction 没有很好实现分布式事务,源代码简单,虽然经过大量的本地测试,源码里面有些情况不知道干什么用,比如?PROVIDER 类型 和?CONSUMER 类型的methodType, 因此个人仅仅当作了解, 不可生产环境使用,但是dubbo proxy 的封装可以学习下,待以后封装时候使用。
(8)个人觉得?fescar 的模型层次更分明,Transaction coordinator ,维护 全局和分支的事务,驱动全局事务的commit 或者 callback 。Transaction Manager, 决定何时开始全局事务,commit 或者 callback 全局事务。Resource Manager, 管理分支上的事务,并将分支事务执行状态报告给?Transaction coordinator?
好了,咱们去看看tcc-transaction 的源码逻辑?
CompensableTransactionAspect:
首先会加载tcc-transation-srping 里面?tcc-transaction.xml, 加载好相关的bean 之后,会调用到CompensableTransactionAspect 的interceptCompensableMethod方法,当我们进入方法之后,发现下面的
TransactionContext transactionContext = FactoryBuilder.factoryOf(compensable.transactionContextEditor()).getInstance().get(pjp.getTarget(), method, pjp.getArgs());
dubbo 的transactionContext 是由 dubbo 的 RpcContext来设置,dubbo RpcContext 是由 threadlocal 原理来实现的。然后再判断是不是合法的t rantransactionConext. 计算methodType 的逻辑有点不太明白作者的思路,因为没有注释,其中经过测试 method type 是root 的表明是 一个事务的根事务,会开启一个全局的事务,?PROVIDER 字面上的意思是服务的提供方,之前全局的事务已经开启了。然后再去判断 try, confirm 和 cancel 状态。
MethodType methodType =CompensableMethodUtils.calculateMethodType(propagation, isTransactionActive, transactionContext);
然后执行?returnValue = pjp.proceed();??
ResourceCoordinatorInterceptor,
?我们看?interceptTransactionContextMethod方法,首先是获取 CompensableTransactionAspect 创建的事务, 如果事务是trying 的状态,就会通过?enlistParticipant 方法,将要执行的?Participant 加入到?transactionManager 中, 以待后面执行。 return pjp.proceed(pjp.getArgs()); 才会执行真正的方法体,任务的异常报错,都会执行?CompensableTransactionInterceptor 的?rootMethodProceed,?transactionManager.rollback(asyncCancel); 将会执行cancel 方法。 此时cancel 方法必须是幂等的而且必须能够回滚之前的操作,这种会对程序员要求很高。?
如果没有异常发生,就会执行?transactionManager.commit(asyncConfirm);,将事务commit 提交,执行confirm 方法,try 方法是方法体,预留资源, confirm 将预留资源 进行确认操作, cancel 就是将预留资源回滚。
DefaultRecoverConfig
这个方法没有看,但是拍脑袋想应该是当事务执行失败时候,进行不断的尝试,因为我觉得生产线上不会使用这个来做尝试机制,还需自己设计
总体感觉没有注释, 没有文档,此外逻辑比较简单,我觉得不适合做dubbo 的分布式事务。
测试代码见下面的github:?https://github.com/dongdongqin/tcc-transaction-demo.git? ??
consumer 那端自己照样子写就好,很简单。