一、前言
嚴(yán)格遵守ACID的分布式事務(wù)我們稱為剛性事務(wù)快集,而遵循BASE理論(基本可用:在故障出現(xiàn)時(shí)保證核心功能可用笛臣,軟狀態(tài):允許中間狀態(tài)出現(xiàn),最終一致性:不要求分布式事務(wù)打成中時(shí)間點(diǎn)數(shù)據(jù)都是一致性的尸饺,但是保證達(dá)到某個(gè)時(shí)間點(diǎn)后进统,數(shù)據(jù)就處于了一致性了)的事務(wù)我們稱為柔性事務(wù),其中TCC編程模式就屬于柔性事務(wù)浪听,本文我們來闡述其理論螟碎。
二、TCC編程模式
TCC編程模式本質(zhì)上也是一種二階段協(xié)議迹栓,不同在于TCC編程模式需要與具體業(yè)務(wù)耦合掉分,下面首先看下TCC編程模式步驟:
所有事務(wù)參與方都需要實(shí)現(xiàn)try,confirm,cancle接口足陨。
事務(wù)發(fā)起方向事務(wù)協(xié)調(diào)器發(fā)起事務(wù)請求孽糖,事務(wù)協(xié)調(diào)器調(diào)用所有事務(wù)參與者的try方法完成資源的預(yù)留,這時(shí)候并沒有真正執(zhí)行業(yè)務(wù)撞叨,而是為后面具體要執(zhí)行的業(yè)務(wù)預(yù)留資源愿吹,這里完成了一階段不从。
如果事務(wù)協(xié)調(diào)器發(fā)現(xiàn)有參與者的try方法預(yù)留資源時(shí)候發(fā)現(xiàn)資源不夠,則調(diào)用參與方的cancle方法回滾預(yù)留的資源犁跪,需要注意cancle方法需要實(shí)現(xiàn)業(yè)務(wù)冪等椿息,因?yàn)橛锌赡苷{(diào)用失敗(比如網(wǎng)絡(luò)原因參與者接受到了請求坷衍,但是由于網(wǎng)絡(luò)原因事務(wù)協(xié)調(diào)器沒有接受到回執(zhí))會(huì)重試寝优。
如果事務(wù)協(xié)調(diào)器發(fā)現(xiàn)所有參與者的try方法返回都OK,則事務(wù)協(xié)調(diào)器調(diào)用所有參與者的confirm方法枫耳,不做資源檢查倡勇,直接進(jìn)行具體的業(yè)務(wù)操作。
如果協(xié)調(diào)器發(fā)現(xiàn)所有參與者的confirm方法都OK了嘉涌,則分布式事務(wù)結(jié)束妻熊。
如果協(xié)調(diào)器發(fā)現(xiàn)有些參與者的confirm方法失敗了,或者由于網(wǎng)絡(luò)原因沒有收到回執(zhí)仑最,則協(xié)調(diào)器會(huì)進(jìn)行重試扔役。這里如果重試一定次數(shù)后還是失敗,會(huì)怎么樣那警医?常見的是做事務(wù)補(bǔ)償亿胸。
螞蟻金服基于TCC實(shí)現(xiàn)了XTS(云上叫DTS)坯钦,目前在螞蟻金服云上有對外輸出,這里我們來結(jié)合其提供的一個(gè)例子來具體理解TCC的含義侈玄,以下引入螞蟻金服云實(shí)例:
“首先我們假想這樣一種場景:轉(zhuǎn)賬服務(wù)婉刀,從銀行 A 某個(gè)賬戶轉(zhuǎn) 100 元錢到銀行 B 的某個(gè)賬戶,銀行 A 和銀行 B 可以認(rèn)為是兩個(gè)單獨(dú)的系統(tǒng)序仙,也就是兩套單獨(dú)的數(shù)據(jù)庫突颊。
我們將賬戶系統(tǒng)簡化成只有賬戶和余額 2 個(gè)字段,并且為了適應(yīng) DTS 的兩階段設(shè)計(jì)要求潘悼,業(yè)務(wù)上又增加了一個(gè)凍結(jié)金額(凍結(jié)金額是指在一筆轉(zhuǎn)賬期間律秃,在一階段的時(shí)候使用該字段臨時(shí)存儲轉(zhuǎn)賬金額,該轉(zhuǎn)賬額度不能被使用治唤,只有等這筆分布式事務(wù)全部提交成功時(shí)棒动,才會(huì)真正的計(jì)入可用余額)。按這樣的設(shè)計(jì)宾添,用戶的可用余額等于賬戶余額減去凍結(jié)金額船惨。這點(diǎn)是理解參與者設(shè)計(jì)的關(guān)鍵,也是 DTS 保證最終一致的業(yè)務(wù)約束缕陕×蝗瘢”
在try階段并沒有對銀行A和B數(shù)據(jù)庫中的余額字段做操作,而是對凍結(jié)金額做的操作榄檬,對應(yīng)A銀行預(yù)留資源操作是對凍結(jié)金額加上100元卜范,這時(shí)候A銀行賬號上可用錢為余額字段-凍結(jié)金額衔统;對應(yīng)B銀行的操作是對凍結(jié)金額上減去100鹿榜,這時(shí)候B銀行賬號上可用的錢為余額字段-凍結(jié)金額。
如果事務(wù)協(xié)調(diào)器調(diào)用銀行A和銀行B的try方法有一個(gè)失敗了(比如銀行A的賬戶余額不夠了)锦爵,則調(diào)用cancle進(jìn)行回滾操作(具體是對凍結(jié)金額做反向操作)舱殿。如果調(diào)用try方法都OK了,則進(jìn)入confirm階段险掀,confirm階段則不做資源檢查沪袭,直接做業(yè)務(wù)操作,對應(yīng)銀行A要在賬戶余額減去100樟氢,然后凍金額減去100冈绊;對應(yīng)銀行B要對賬戶余額字段加上100,然后凍結(jié)金額加上100埠啃。
最關(guān)心的死宣,如果confirm階段如果有一個(gè)參與者失敗了,該如何處理碴开,其實(shí)上面操作都是xts-client做的毅该,還有一個(gè)xts-server專門做事務(wù)補(bǔ)償?shù)摹?/p>
三博秫、總結(jié)
TCC是對二階段的一個(gè)改進(jìn),try階段通過預(yù)留資源的方式避免了同步阻塞資源的情況眶掌,但是TCC編程需要業(yè)務(wù)自己實(shí)現(xiàn)try,confirm,cancle方法挡育,對業(yè)務(wù)入侵太大,實(shí)現(xiàn)起來也比較復(fù)雜朴爬。
最后
想了解JDK NIO和更多Netty基礎(chǔ)的可以單擊我
想了解更多關(guān)于粘包半包問題單擊我
更多關(guān)于分布式系統(tǒng)中服務(wù)降級策略的知識可以單擊 單擊我
想系統(tǒng)學(xué)dubbo的單擊我
想學(xué)并發(fā)的童鞋可以 單擊我
想了解SpringBoot核心模塊原理的 單擊我