一個(gè)TCC事務(wù)框架需要解決的當(dāng)然是分布式事務(wù)的管理。關(guān)于TCC事務(wù)機(jī)制的介紹姻报,可以參考TCC事務(wù)機(jī)制簡介间螟。 TCC事務(wù)模型雖然說起來簡單厢破,然而要基于TCC實(shí)現(xiàn)一個(gè)通用的分布式事務(wù)框架,卻比它看上去要復(fù)雜的多笆焰,不只是簡單的調(diào)用一下Confirm/Cancel業(yè)務(wù)就可以了的见坑。
本文將以Spring容器為例荞驴,試圖分析一下,實(shí)現(xiàn)一個(gè)通用的TCC分布式事務(wù)框架需要注意的一些問題粟焊。
一、TCC全局事務(wù)必須基于RM本地事務(wù)來實(shí)現(xiàn)全局事務(wù)
TCC服務(wù)是由Try/Confirm/Cancel業(yè)務(wù)構(gòu)成的悲雳, 其Try/Confirm/Cancel業(yè)務(wù)在執(zhí)行時(shí)香追,會(huì)訪問資源管理器(Resource Manager透典,下文簡稱RM)來存取數(shù)據(jù)。這些存取操作税弃,必須要參與RM本地事務(wù)凑队,以使其更改的數(shù)據(jù)要么都commit漩氨,要么都rollback。
這一點(diǎn)不難理解款青,考慮一下如下場景:
假設(shè)圖中的服務(wù)B沒有基于RM本地事務(wù)(以RDBS為例可都,可通過設(shè)置auto-commit為true來模擬)蚓耽,那么一旦[B:Try]操作中途執(zhí)行失敗旋炒,TCC事務(wù)框架后續(xù)決定回滾全局事務(wù)時(shí),該[B:Cancel]則需要判斷[B:Try]中哪些操作已經(jīng)寫到DB鼎兽、哪些操作還沒有寫到DB:假設(shè)[B:Try]業(yè)務(wù)有5個(gè)寫庫操作铣除,[B:Cancel]業(yè)務(wù)則需要逐個(gè)判斷這5個(gè)操作是否生效尚粘,并將生效的操作執(zhí)行反向操作。 不幸的是秉继,由于[B:Cancel]業(yè)務(wù)也有n(0<=n<=5)個(gè)反向的寫庫操作尚辑,此時(shí)一旦[B:Cancel]也中途出錯(cuò),則后續(xù)的[B:Cancel]執(zhí)行任務(wù)更加繁重月褥。因?yàn)槠昂恚啾鹊谝淮蝃B:Cancel]操作灯荧,后續(xù)的[B:Cancel]操作還需要判斷先前的[B:Cancel]操作的n(0<=n<=5)個(gè)寫庫中哪幾個(gè)已經(jīng)執(zhí)行、哪幾個(gè)還沒有執(zhí)行哆窿,這就涉及到了冪等性問題挚躯。而對冪等性的保障擦秽,又很可能還需要涉及額外的寫庫操作,該寫庫操作又會(huì)因?yàn)闆]有RM本地事務(wù)的支持而存在類似問題缩搅。硼瓣。置谦∶较浚可想而知,如果不基于RM本地事務(wù)谅阿,TCC事務(wù)框架是無法有效的管理TCC全局事務(wù)的。
反之敏晤,基于RM本地事務(wù)的TCC事務(wù)缅茉,這種情況則會(huì)很容易處理:[B:Try]操作中途執(zhí)行失敗蔬墩,TCC事務(wù)框架將其參與RM本地事務(wù)直接rollback即可。后續(xù)TCC事務(wù)框架決定回滾全局事務(wù)時(shí)奏司,在知道“[B:Try]操作涉及的RM本地事務(wù)已經(jīng)rollback”的情況下樟插,根本無需執(zhí)行[B:Cancel]操作黄锤。
換句話說,基于RM本地事務(wù)實(shí)現(xiàn)TCC事務(wù)框架時(shí)副编,一個(gè)TCC型服務(wù)的cancel業(yè)務(wù)要么執(zhí)行痹届,要么不執(zhí)行打月,不需要考慮部分執(zhí)行的情況奏篙。
二、TCC事務(wù)框架應(yīng)該接管Spring容器的TransactionManager
基于RM本地事務(wù)的TCC事務(wù)框架,可以將各Try/Confirm/Cancel業(yè)務(wù)看著一個(gè)原子服務(wù):一個(gè)RM本地事務(wù)提交充易,參與該RM本地事務(wù)的所有Try/Confirm/Cancel業(yè)務(wù)操作都生效荸型;反之,則都不生效梭冠。掌握每個(gè)RM本地事務(wù)的狀態(tài)以及它們與Try/Confirm/Cancel業(yè)務(wù)方法之間的對應(yīng)關(guān)系改备,以此為基礎(chǔ)悬钳,TCC事務(wù)框架才能有效的構(gòu)建TCC全局事務(wù)。
TCC服務(wù)的Try/Confirm/Cancel業(yè)務(wù)方法在RM上的數(shù)據(jù)存取操作碉渡,其RM本地事務(wù)是由Spring容器的PlatformTransactionManager來commit/rollback的滞诺,TCC事務(wù)框架想要了解RM本地事務(wù)的狀態(tài)环疼,只能通過接管Spring的事務(wù)管理器功能秦爆。
2.1. 為什么TCC事務(wù)框架需要掌握RM本地事務(wù)的狀態(tài)?首先爸吮,根據(jù)TCC機(jī)制的定義形娇,TCC事務(wù)是通過執(zhí)行Cancel業(yè)務(wù)來達(dá)到回滾效果的筹误。仔細(xì)分析一下厨剪,這里暗含一個(gè)事實(shí): 只有生效的Try業(yè)務(wù)操作才需要執(zhí)行對應(yīng)的Cancel業(yè)務(wù)操作。換句話說陶衅,只有Try業(yè)務(wù)操作所參與的RM本地事務(wù)被commit了搀军,后續(xù)TCC全局事務(wù)回滾時(shí)才需要執(zhí)行其對應(yīng)的Cancel業(yè)務(wù)操作;否則焚刺,如果Try業(yè)務(wù)操作所參與的RM本地事務(wù)被rollback了乳愉,后續(xù)TCC全局事務(wù)回滾時(shí)就不能執(zhí)行其Cancel業(yè)務(wù)诅福,此時(shí)若盲目執(zhí)行Cancel業(yè)務(wù)反而會(huì)導(dǎo)致數(shù)據(jù)不一致氓润。
其次,Confirm/Cancel業(yè)務(wù)操作必須保證生效挨措。Confirm/Cancel業(yè)務(wù)操作也會(huì)涉及RM數(shù)據(jù)存取操作浅役,其參與的RM本地事務(wù)也必須被commit伶唯。TCC事務(wù)框架需要在確切的知道所有Confirm/Cancel業(yè)務(wù)操作參與的RM本地事務(wù)都被成功commit后乳幸,才能將標(biāo)記該TCC全局事務(wù)為完成粹断。如果TCC事務(wù)框架誤判了Confirm/Cancel業(yè)務(wù)參與RM本地事務(wù)的狀態(tài),就會(huì)造成全局事務(wù)不一致希柿。
最后曾撤,未完成的TCC全局晕粪,TCC事務(wù)框架必須重新嘗試提交/回滾操作兵多。重試時(shí)會(huì)再次調(diào)用各TCC服務(wù)的Confirm/Cancel業(yè)務(wù)操作。如果某個(gè)服務(wù)的Confirm/Cancel業(yè)務(wù)之前已經(jīng)生效(其參與的RM本地事務(wù)已經(jīng)提交)衅斩,重試時(shí)就不應(yīng)該再次被調(diào)用畏梆。否則奠涌,其Confirm/Cancel業(yè)務(wù)被多次調(diào)用磷杏,就會(huì)有“服務(wù)冪等性”的問題极祸。
2.2. 攔截TCC服務(wù)的Try/Confirm/Cancel業(yè)務(wù)方法的執(zhí)行,根據(jù)其異常信息可否知道其RM本地事務(wù)是否commit/rollback了呢浴捆?基本上很難做到选泻。為什么這么說呢美莫? 第一茂嗓,事務(wù)是可以在多個(gè)(本地/遠(yuǎn)程)服務(wù)之間互相傳播其事務(wù)上下文的述吸,一個(gè)業(yè)務(wù)方法(Try/Confirm/Cancel)執(zhí)行完畢并不一定會(huì)觸發(fā)當(dāng)前事務(wù)的commit/rollback操作。比如道批,被傳播事務(wù)上下文的業(yè)務(wù)方法隆豹,在它開始執(zhí)行時(shí)璃赡,容器并不會(huì)為其創(chuàng)建新的事務(wù),而是它的調(diào)用方參與的事務(wù)塌计,使得二者操作在同一個(gè)事務(wù)中锌仅;同樣墙贱,在它執(zhí)行完畢時(shí)惨撇,容器也不會(huì)提交/回滾它參與的事務(wù)的魁衙。因此,這類業(yè)務(wù)方法上的異常情況并不能反映他們是否生效榄笙。不接管Spring的TransactionManager茅撞,就無法了解事務(wù)于何時(shí)被創(chuàng)建米丘,也無法了解它于何時(shí)被提交/回滾糊啡。 第二棚蓄、一個(gè)業(yè)務(wù)方法可能會(huì)包含多個(gè)RM本地事務(wù)的情況梭依。比如: A(REQUIRED)->B(REQUIRES_NEW)->C(REQUIRED),這種情況下糊探,A服務(wù)所參與的RM本地事務(wù)被提交時(shí)科平,B服務(wù)和C服務(wù)參與的RM本地事務(wù)則可能會(huì)被回滾瞪慧。 第三、并不是拋出了異常的業(yè)務(wù)方法,其參與的事務(wù)就回滾了矢腻。Spring容器的聲明式事務(wù)定義了兩類異常多柑,其事務(wù)完成方向都不一樣:系統(tǒng)異常(一般為Unchecked異常楣责,默認(rèn)事務(wù)完成方向是rollback)秆麸、應(yīng)用異常(一般為Checked異常沮趣,默認(rèn)事務(wù)完成方向是commit)房铭。二者的事務(wù)完成方向又可以通過@Transactional配置顯式的指定,如rollbackFor/noRollbackFor等翁狐。 第四露懒、Spring容器還支持使用setRollbackOnly的方式顯式的控制事務(wù)完成方向隐锭; 最后钦睡、自行攔截業(yè)務(wù)方法的攔截器和Spring的事務(wù)處理的攔截器還會(huì)存在執(zhí)行先后躁倒、攔截范圍不同等問題。例如衰抑,如果自行攔截器執(zhí)行在前呛踊,就會(huì)出現(xiàn)業(yè)務(wù)方法雖然已經(jīng)執(zhí)行完畢但此時(shí)其參與的RM本地事務(wù)還沒有commit/rollback谭网。
TCC事務(wù)框架的定位應(yīng)該是一個(gè)TransactionManager愉择,其職責(zé)是負(fù)責(zé)commit/rollback事務(wù)织中。而一個(gè)事務(wù)應(yīng)該commit狭吼、還是rollback刁笙,則應(yīng)該是由Spring容器來決定的:Spring決定提交事務(wù)時(shí)采盒,會(huì)調(diào)用TransactionManager來完成commit操作磅氨;Spring決定回滾事務(wù)時(shí),會(huì)調(diào)用TransactionManager來完成rollback操作延赌。
接管Spring容器的TransactionManager挫以,TCC事務(wù)框架可以明確的得到Spring的事務(wù)性指令掐松,并管理Spring容器中各服務(wù)的RM本地事務(wù)大磺。否則杠愧,如果通過自行攔截的機(jī)制,則使得業(yè)務(wù)系統(tǒng)存在TCC事務(wù)處理锐锣、RM本地事務(wù)處理兩套事務(wù)處理邏輯雕憔,二者互不通信,各行其是姨丈。這種情況下要協(xié)調(diào)TCC全局事務(wù)擅腰,基本上可以說是緣木求魚趁冈,本地事務(wù)尚且無法管理渗勘,更何談管理分布式事務(wù)旺坠?
三取刃、TCC事務(wù)框架應(yīng)該具備故障恢復(fù)機(jī)制
一個(gè)TCC事務(wù)框架蹋肮,若是沒有故障恢復(fù)的保障,是不成其為分布式事務(wù)框架的璧疗。
分布式事務(wù)管理框架的職責(zé)坯辩,不是做出全局事務(wù)提交/回滾的指令,而是管理全局事務(wù)提交/回滾的過程崩侠。它需要能夠協(xié)調(diào)多個(gè)RM資源漆魔、多個(gè)節(jié)點(diǎn)的分支事務(wù),保證它們按全局事務(wù)的完成方向各自完成自己的分支事務(wù)。這一點(diǎn)有送,是不容易做到的。因?yàn)槿刚瑢?shí)際應(yīng)用中裸删,會(huì)有各種故障出現(xiàn),很多都會(huì)造成事務(wù)的中斷阵赠,從而使得統(tǒng)一提交/回滾全局事務(wù)的目標(biāo)不能達(dá)到涯塔,甚至出現(xiàn)”一部分分支事務(wù)已經(jīng)提交,而另一部分分支事務(wù)則已回滾”的情況清蚀。比較常見的故障匕荸,比如:業(yè)務(wù)系統(tǒng)服務(wù)器宕機(jī)、重啟枷邪;數(shù)據(jù)庫服務(wù)器宕機(jī)榛搔、重啟;網(wǎng)絡(luò)故障东揣;斷電等践惑。這些故障可能單獨(dú)發(fā)生,也可能會(huì)同時(shí)發(fā)生嘶卧。作為分布式事務(wù)框架尔觉,應(yīng)該具備相應(yīng)的故障恢復(fù)機(jī)制,無視這些故障的影響是不負(fù)責(zé)任的做法芥吟。
一個(gè)完整的分布式事務(wù)框架侦铜,應(yīng)該保障即使在最嚴(yán)苛的條件下也能保證全局事務(wù)的一致性,而不是只能在最理想的環(huán)境下才能提供這種保障钟鸵。退一步說钉稍,如果能有所謂“理想的環(huán)境”,那也無需使用分布式事務(wù)了棺耍。
TCC事務(wù)框架要支持故障恢復(fù)嫁盲,就必須記錄相應(yīng)的事務(wù)日志。事務(wù)日志是故障恢復(fù)的基礎(chǔ)和前提烈掠,它記錄了事務(wù)的各項(xiàng)數(shù)據(jù)羞秤。TCC事務(wù)框架做故障恢復(fù)時(shí),可以根據(jù)事務(wù)日志的數(shù)據(jù)將中斷的事務(wù)恢復(fù)至正確的狀態(tài)左敌,并在此基礎(chǔ)上繼續(xù)執(zhí)行先前未完成的提交/回滾操作瘾蛋。
四、TCC事務(wù)框架應(yīng)該提供Confirm/Cancel服務(wù)的冪等性保障
一般認(rèn)為矫限,服務(wù)的冪等性哺哼,是指針對同一個(gè)服務(wù)的多次(n>1)請求和對它的單次(n=1)請求佩抹,二者具有相同的副作用。
在TCC事務(wù)模型中取董,Confirm/Cancel業(yè)務(wù)可能會(huì)被重復(fù)調(diào)用棍苹,其原因很多。比如茵汰,全局事務(wù)在提交/回滾時(shí)會(huì)調(diào)用各TCC服務(wù)的Confirm/Cancel業(yè)務(wù)邏輯枢里。執(zhí)行這些Confirm/Cancel業(yè)務(wù)時(shí),可能會(huì)出現(xiàn)如網(wǎng)絡(luò)中斷的故障而使得全局事務(wù)不能完成蹂午。因此栏豺,故障恢復(fù)機(jī)制后續(xù)仍然會(huì)重新提交/回滾這些未完成的全局事務(wù),這樣就會(huì)再次調(diào)用參與該全局事務(wù)的各TCC服務(wù)的Confirm/Cancel業(yè)務(wù)邏輯豆胸。
既然Confirm/Cancel業(yè)務(wù)可能會(huì)被多次調(diào)用奥洼,就需要保障其冪等性。 那么晚胡,應(yīng)該由TCC事務(wù)框架來提供冪等性保障灵奖?還是應(yīng)該由業(yè)務(wù)系統(tǒng)自行來保障冪等性呢? 個(gè)人認(rèn)為估盘,應(yīng)該是由TCC事務(wù)框架來提供冪等性保障瓷患。如果僅僅只是極個(gè)別服務(wù)存在這個(gè)問題的話,那么由業(yè)務(wù)系統(tǒng)來負(fù)責(zé)也是可以的忿檩;然而尉尾,這是一類公共問題爆阶,毫無疑問燥透,所有TCC服務(wù)的Confirm/Cancel業(yè)務(wù)存在冪等性問題。TCC服務(wù)的公共問題應(yīng)該由TCC事務(wù)框架來解決辨图;而且班套,考慮一下由業(yè)務(wù)系統(tǒng)來負(fù)責(zé)冪等性需要考慮的問題,就會(huì)發(fā)現(xiàn)故河,這無疑增大了業(yè)務(wù)系統(tǒng)的復(fù)雜度吱韭。
五、TCC事務(wù)框架不能盲目的依賴Cancel業(yè)務(wù)來回滾事務(wù)
前文以及提到過鱼的,TCC事務(wù)通過Cancel業(yè)務(wù)來對Try業(yè)務(wù)進(jìn)行回撤的機(jī)制暗含了一個(gè)事實(shí):Try操作已經(jīng)生效理盆。也就是說,只有Try操作所參與的RM本地事務(wù)已經(jīng)提交的情況下凑阶,才需要執(zhí)行其Cancel操作進(jìn)行回撤猿规。沒有執(zhí)行、或者執(zhí)行了但是其RM本地事務(wù)被rollback的Try業(yè)務(wù)宙橱,是一定不能執(zhí)行其Cancel業(yè)務(wù)進(jìn)行回撤的姨俩。因此蘸拔,TCC事務(wù)框架在全局事務(wù)回滾時(shí),應(yīng)該根據(jù)TCC服務(wù)的Try業(yè)務(wù)的執(zhí)行情況選擇合適的處理機(jī)制环葵。而不能盲目的執(zhí)行Cancel業(yè)務(wù)调窍,否則就會(huì)導(dǎo)致數(shù)據(jù)不一致。
一個(gè)TCC服務(wù)的Try操作是否生效张遭,這是TCC事務(wù)框架應(yīng)該知道的邓萨,因?yàn)槠銽ry業(yè)務(wù)所參與的RM事務(wù)也是由TCC事務(wù)框架所commit/rollbac的(前提是TCC事務(wù)框架接管了Spring的事務(wù)管理器)。所以帝璧,TCC事務(wù)回滾時(shí)先誉,TCC事務(wù)框架可考慮如下處理策略: 1)如果TCC事務(wù)框架發(fā)現(xiàn)某個(gè)服務(wù)的Try操作的本地事務(wù)尚未提交,應(yīng)該直接將其回滾的烁,而后就不必再執(zhí)行該服務(wù)的cancel業(yè)務(wù)褐耳; 2)如果TCC事務(wù)框架發(fā)現(xiàn)某個(gè)服務(wù)的Try操作的本地事務(wù)已經(jīng)回滾,則不必再執(zhí)行該服務(wù)的cancel業(yè)務(wù)渴庆; 3)如果TCC事務(wù)框架發(fā)現(xiàn)某個(gè)服務(wù)的Try操作尚未被執(zhí)行過铃芦,那么,也不必再執(zhí)行該服務(wù)的cancel業(yè)務(wù)襟雷。
總之刃滓,TCC事務(wù)框架應(yīng)該保障: 1)已生效的Try操作應(yīng)該被其Cancel操作所回撤; 2)尚未生效的Try操作耸弄,則不應(yīng)該執(zhí)行其Cancel操作咧虎。這一點(diǎn),不是冪等性所能解決的問題计呈。如上文所述砰诵,冪等性是指服務(wù)被執(zhí)行一次和被執(zhí)行n(n>0)次所產(chǎn)生的影響相同。但是捌显,未被執(zhí)行和被執(zhí)行過茁彭,二者效果肯定是不一樣的,這不屬于冪等性的范疇扶歪。
六理肺、Cancel業(yè)務(wù)與Try業(yè)務(wù)并行,甚至先于Try操作完成
這應(yīng)該算TCC事務(wù)機(jī)制特有的一個(gè)不可思議的陷阱善镰。一般來說妹萨,一個(gè)特定的TCC服務(wù),其Try操作的執(zhí)行炫欺,是應(yīng)該在其Confirm/Cancel操作之前的乎完。Try操作執(zhí)行完畢之后,Spring容器再根據(jù)Try操作的執(zhí)行情況竣稽,指示TCC事務(wù)框架提交/回滾全局事務(wù)囱怕。然后霍弹,TCC事務(wù)框架再去逐個(gè)調(diào)用各TCC服務(wù)的Confirm/Cancel操作。
然而娃弓,超時(shí)典格、網(wǎng)絡(luò)故障、服務(wù)器的重啟等故障的存在台丛,使得這個(gè)順序會(huì)被打亂耍缴。比如:
上圖中,假設(shè)[B:Try]操作執(zhí)行過程中挽霉,網(wǎng)絡(luò)閃斷防嗡,[A:Try]會(huì)收到一個(gè)RPC遠(yuǎn)程調(diào)用異常。A不處理該異常侠坎,導(dǎo)致全局事務(wù)決定回滾蚁趁,TCC事務(wù)框架就會(huì)去調(diào)用[B:Cancel],而此刻A实胸、B之間網(wǎng)絡(luò)剛好已經(jīng)恢復(fù)他嫡。如果[B:Try]操作耗時(shí)較長(網(wǎng)絡(luò)阻塞/數(shù)據(jù)庫操作阻塞),就會(huì)出現(xiàn)[B:Try]和[B:Cancel]二者并行處理的現(xiàn)象庐完,甚至[B:Cancel]先完成的現(xiàn)象钢属。
這種情況下,由于[B:Cancel]執(zhí)行時(shí)门躯,[B:Try]尚未生效(其RM本地事務(wù)尚未提交)淆党,因此,[B:Cancel]是不能執(zhí)行的讶凉,至少是不能生效(執(zhí)行了其RM本地事務(wù)也要rollback)的染乌。然而,當(dāng) [B:Cancel]處理完畢(跳過執(zhí)行缀遍、或者執(zhí)行后rollback其RM本地事務(wù))后慕匠,[B:Try]操作完成又生效了(其RM本地事務(wù)成功提交)饱须,這就會(huì)使得[B:Cancel]雖然提供了域醇,但卻沒有起到回撤[B:Try]的作用,導(dǎo)致數(shù)據(jù)的不一致蓉媳。
所以譬挚,TCC框架在這種情況下,需要: 1)將[B:Try]的本地事務(wù)標(biāo)注為rollbackOnly酪呻,阻止其后續(xù)生效减宣; 2)禁止其再次將事務(wù)上下文傳遞給其他遠(yuǎn)程分支,否則該問題將在其他分支上出現(xiàn)玩荠; 3)相應(yīng)地漆腌,[B:Cancel]也不必執(zhí)行贼邓,至少不能生效。
當(dāng)然闷尿,TCC事務(wù)框架也可以簡單的選擇阻塞[B:Cancel]的處理塑径,待[B:Try]執(zhí)行完畢后,再根據(jù)它的執(zhí)行情況判斷是否需要執(zhí)行[B:Cancel]填具。不過统舀,這種處理方式因?yàn)樾枰却岳途埃幚硇噬蠒?huì)有所不及誉简。
同樣的情況也會(huì)出現(xiàn)在confirm業(yè)務(wù)上,只不過盟广,發(fā)生在Confirm業(yè)務(wù)上的處理邏輯與發(fā)生在Cancel業(yè)務(wù)上的處理邏輯會(huì)不一樣闷串,TCC框架必須保證: 1)Confirm業(yè)務(wù)在Try業(yè)務(wù)之后執(zhí)行,若發(fā)現(xiàn)并行筋量,則只能阻塞相應(yīng)的Confirm業(yè)務(wù)操作窿克; 2)在進(jìn)入Confirm執(zhí)行階段之后,也不可以再提交同一全局事務(wù)內(nèi)的新的Try操作的RM本地事務(wù)毛甲。
七年叮、TCC服務(wù)復(fù)用性是不是相對較差?
TCC事務(wù)機(jī)制的定義玻募,決定了一個(gè)服務(wù)需要提供三個(gè)業(yè)務(wù)實(shí)現(xiàn):Try業(yè)務(wù)只损、Confirm業(yè)務(wù)、Cancel業(yè)務(wù)七咧≡颈梗可能會(huì)有人因此認(rèn)為TCC服務(wù)的復(fù)用性較差。怎么說呢艾栋,要是將 Try/Confirm/Cancel業(yè)務(wù)邏輯單獨(dú)拿出來復(fù)用爆存,其復(fù)用性當(dāng)然是不好的,Try/Confirm/Cancel 邏輯作為TCC型服務(wù)中的一部分蝗砾,是不能單獨(dú)作為一個(gè)組件來復(fù)用的先较。Try、Confirm悼粮、Cancel業(yè)務(wù)共同才構(gòu)成一個(gè)組件闲勺,如果要復(fù)用,應(yīng)該是復(fù)用整個(gè)TCC服務(wù)組件扣猫,而不是單獨(dú)的Try/Confirm/Cancel業(yè)務(wù)菜循。
八、TCC服務(wù)是否需要對外暴露三個(gè)服務(wù)接口申尤?")**八癌幕、TCC服務(wù)是否需要對外暴露三個(gè)服務(wù)接口衙耕?
不需要。TCC服務(wù)與普通的服務(wù)一樣勺远,只需要暴露一個(gè)接口臭杰,也就是它的Try業(yè)務(wù)。Confirm/Cancel業(yè)務(wù)邏輯谚中,只是因?yàn)槿质聞?wù)提交/回滾的需要才提供的渴杆,因此Confirm/Cancel業(yè)務(wù)只需要被TCC事務(wù)框架發(fā)現(xiàn)即可,不需要被調(diào)用它的其他業(yè)務(wù)服務(wù)所感知宪塔。
換句話說磁奖,業(yè)務(wù)系統(tǒng)的其他服務(wù)在需要調(diào)用TCC服務(wù)時(shí),根本不需要知道它是否為TCC型服務(wù)某筐。因?yàn)楸却睿琓CC服務(wù)能被其他業(yè)務(wù)服務(wù)調(diào)用的也僅僅是其Try業(yè)務(wù),Confirm/Cancel業(yè)務(wù)是不能被其他業(yè)務(wù)服務(wù)直接調(diào)用的南誊。
九身诺、TCC服務(wù)A的Confirm/Cancel業(yè)務(wù)中能否調(diào)用它依賴的TCC服務(wù)B的Confirm/Cancel業(yè)務(wù)?
最好是不要這樣做抄囚。首先霉赡,沒有必要。TCC服務(wù)A依賴TCC服務(wù)B幔托,那么[A:Try]已經(jīng)將事務(wù)上下文傳播給[B:Try]了穴亏,后續(xù)由TCC事務(wù)框架來調(diào)用各自的Confirm/Cancel業(yè)務(wù)即可;其次重挑,Confirm/Cancel業(yè)務(wù)如果被允許調(diào)用其他服務(wù)嗓化,那么它就有可能再次發(fā)起新的TCC全局事務(wù)。如此遞歸下去谬哀,將會(huì)導(dǎo)致全局事務(wù)關(guān)系混亂且不可控刺覆。
TCC全局事務(wù),應(yīng)該盡量在Try操作階段傳播事務(wù)上下文史煎。Confirm/Cancel操作階段僅需要完成各自Try業(yè)務(wù)操作的確認(rèn)操作/補(bǔ)償操作即可谦屑,不適合再做遠(yuǎn)程調(diào)用,更不能再對外傳播事務(wù)上下文劲室。
綜上所述伦仍,本文傾向于認(rèn)為结窘,實(shí)現(xiàn)一個(gè)通用的TCC分布式事務(wù)管理框架很洋,還是相對比較復(fù)雜的。一般業(yè)務(wù)系統(tǒng)如果需要使用TCC事務(wù)機(jī)制隧枫,并不推薦自行設(shè)計(jì)實(shí)現(xiàn)喉磁。 這里谓苟,給大家推薦一款開源的TCC分布式事務(wù)管理器?ByteTCC?。ByteTCC基于Try/Confirm/Cancel機(jī)制實(shí)現(xiàn)协怒,可與Spring容器無縫集成涝焙,兼容Spring的聲明式事務(wù)管理。提供對dubbo框架孕暇、Spring Cloud的開箱即用的支持仑撞,可滿足多數(shù)據(jù)源、跨應(yīng)用妖滔、跨服務(wù)器等各種分布式事務(wù)場景的需求隧哮。
在此我向大家推薦一個(gè)架構(gòu)學(xué)習(xí)交流群。交流學(xué)習(xí)群號(hào):938837867 暗號(hào):555 里面會(huì)分享一些資深架構(gòu)師錄制的視頻錄像:有Spring座舍,MyBatis沮翔,Netty源碼分析,高并發(fā)曲秉、高性能采蚀、分布式、微服務(wù)架構(gòu)的原理承二,JVM性能優(yōu)化榆鼠、分布式架構(gòu)等這些成為架構(gòu)師必備