需求: Dubbo 如何做分布式事務(wù)?? 除了fescar 那么高深的框架,今天來學(xué)習(xí)一下 tcc-transaction, github 上的star 有3000多個(gè)(https://github.com/changmingxie/tcc-transaction.git)免姿。
介紹:
(1). tcc 指的是 try, cancel, confirm牵祟, 在 tcc-transaction 的源碼中薯蝎, cancel 和confirm 沒有做冪等性控制啃擦,?需要程序員手動(dòng)的保證他們的冪等性业舍。?
(2). tcc-transaction 主要是通過補(bǔ)償性的措施來保證分布式事務(wù)的。通過注解Compensable雀鹃, 指定confirmMethod 和?cancelMethod 的名字。
(3). tcc-transaction 對dubbo 的支持励两,是通過重新 擴(kuò)展 proxyFactory 的 spi黎茎,實(shí)現(xiàn)了Tccjavassist 和 tccjdk 方式來重新生成帶有?Compensable 注解的 代理類。 原聲的dubbo proxyFactory 是不能夠生成帶有?Compensable 注解的 代理類的当悔。
(4).tcc-transaction 主要是通過spring 的 AOP 中 通知環(huán)繞的方式傅瞻,來處理?Compensable 注解。
(5) 源代碼中?CompensableTransactionAspect (先執(zhí)行)和?ResourceCoordinatorInterceptor (后執(zhí)行) 是兩個(gè) 切面盲憎,執(zhí)行的順序依靠 spring core 中的 order 的大小嗅骄, 越小 執(zhí)行的順序越是提前,CompensableTransactionAspect 的執(zhí)行 order 是?Ordered.HIGHEST_PRECEDENCE饼疙。
(6) 通過AOP的環(huán)繞通知溺森,我們知道 類 中CompensableTransactionInterceptor 調(diào)用?pjp.proceed() 不會執(zhí)行 目標(biāo) method, 反而會執(zhí)行?ResourceCoordinatorInterceptor 中的?interceptTransactionContextMethod方法,ResourceCoordinatorInterceptor 中的?pjp.proceed(pjp.getArgs())方法屏积,才會調(diào)用執(zhí)行目標(biāo)方法澡罚。
好了, 首先得弄清楚tcc-transaction 給我們提供的案例肾请,大家先倒入sql留搔,比較全的那個(gè)sql 文檔,含有is_deleted 字段铛铁,然后用tomcat 啟動(dòng)是完全可以執(zhí)行的隔显,同時(shí)我嘗試的springboot start dubbo 版本也會放到github 上的,大家可以嘗試用我的案例 結(jié)合springboot dubbo 應(yīng)用去更好的解決分布式事務(wù)問題饵逐。
(7)個(gè)人覺得 tcc-transaction 沒有很好實(shí)現(xiàn)分布式事務(wù)括眠,源代碼簡單,雖然經(jīng)過大量的本地測試倍权,源碼里面有些情況不知道干什么用掷豺,比如?PROVIDER 類型 和?CONSUMER 類型的methodType, 因此個(gè)人僅僅當(dāng)作了解薄声, 不可生產(chǎn)環(huán)境使用当船,但是dubbo proxy 的封裝可以學(xué)習(xí)下,待以后封裝時(shí)候使用默辨。
(8)個(gè)人覺得?fescar 的模型層次更分明德频,Transaction coordinator ,維護(hù) 全局和分支的事務(wù)缩幸,驅(qū)動(dòng)全局事務(wù)的commit 或者 callback 壹置。Transaction Manager, 決定何時(shí)開始全局事務(wù),commit 或者 callback 全局事務(wù)表谊。Resource Manager, 管理分支上的事務(wù)钞护,并將分支事務(wù)執(zhí)行狀態(tài)報(bào)告給?Transaction coordinator?
好了,咱們?nèi)タ纯磘cc-transaction 的源碼邏輯?
CompensableTransactionAspect:
首先會加載tcc-transation-srping 里面?tcc-transaction.xml爆办, 加載好相關(guān)的bean 之后难咕,會調(diào)用到CompensableTransactionAspect 的interceptCompensableMethod方法,當(dāng)我們進(jìn)入方法之后押逼,發(fā)現(xiàn)下面的
TransactionContext transactionContext = FactoryBuilder.factoryOf(compensable.transactionContextEditor()).getInstance().get(pjp.getTarget(), method, pjp.getArgs());
dubbo 的transactionContext 是由 dubbo 的 RpcContext來設(shè)置步藕,dubbo RpcContext 是由 threadlocal 原理來實(shí)現(xiàn)的。然后再判斷是不是合法的t rantransactionConext. 計(jì)算methodType 的邏輯有點(diǎn)不太明白作者的思路挑格,因?yàn)闆]有注釋咙冗,其中經(jīng)過測試 method type 是root 的表明是 一個(gè)事務(wù)的根事務(wù),會開啟一個(gè)全局的事務(wù)漂彤,?PROVIDER 字面上的意思是服務(wù)的提供方雾消,之前全局的事務(wù)已經(jīng)開啟了灾搏。然后再去判斷 try, confirm 和 cancel 狀態(tài)立润。
MethodType methodType =CompensableMethodUtils.calculateMethodType(propagation, isTransactionActive, transactionContext);
然后執(zhí)行?returnValue = pjp.proceed();??
ResourceCoordinatorInterceptor狂窑,
?我們看?interceptTransactionContextMethod方法,首先是獲取 CompensableTransactionAspect 創(chuàng)建的事務(wù)桑腮, 如果事務(wù)是trying 的狀態(tài)泉哈,就會通過?enlistParticipant 方法,將要執(zhí)行的?Participant 加入到?transactionManager 中破讨, 以待后面執(zhí)行丛晦。 return pjp.proceed(pjp.getArgs()); 才會執(zhí)行真正的方法體,任務(wù)的異常報(bào)錯(cuò)提陶,都會執(zhí)行?CompensableTransactionInterceptor 的?rootMethodProceed烫沙,?transactionManager.rollback(asyncCancel); 將會執(zhí)行cancel 方法。 此時(shí)cancel 方法必須是冪等的而且必須能夠回滾之前的操作隙笆,這種會對程序員要求很高锌蓄。?
如果沒有異常發(fā)生,就會執(zhí)行?transactionManager.commit(asyncConfirm);撑柔,將事務(wù)commit 提交瘸爽,執(zhí)行confirm 方法,try 方法是方法體乏冀,預(yù)留資源蝶糯, confirm 將預(yù)留資源 進(jìn)行確認(rèn)操作, cancel 就是將預(yù)留資源回滾辆沦。
DefaultRecoverConfig
這個(gè)方法沒有看,但是拍腦袋想應(yīng)該是當(dāng)事務(wù)執(zhí)行失敗時(shí)候识虚,進(jìn)行不斷的嘗試肢扯,因?yàn)槲矣X得生產(chǎn)線上不會使用這個(gè)來做嘗試機(jī)制,還需自己設(shè)計(jì)
總體感覺沒有注釋担锤, 沒有文檔蔚晨,此外邏輯比較簡單,我覺得不適合做dubbo 的分布式事務(wù)肛循。
測試代碼見下面的github:?https://github.com/dongdongqin/tcc-transaction-demo.git? ??
consumer 那端自己照樣子寫就好铭腕,很簡單。