兩階段提交(2PC)
?????????XA是X/Open CAE Specification (Distributed Transaction Processing)模型中定義的TM(Transaction Manager)與RM(Resource Manager)之間進(jìn)行通信的接口。
?? ?????在XA規(guī)范中,數(shù)據(jù)庫(kù)充當(dāng)RM角色,應(yīng)用需要充當(dāng)TM的角色,即生成全局的txId,調(diào)用XAResource接口,把多個(gè)本地事務(wù)協(xié)調(diào)為全局統(tǒng)一的分布式事務(wù)。
????????二階段提交是XA的標(biāo)準(zhǔn)實(shí)現(xiàn)。它將分布式事務(wù)的提交拆分為2個(gè)階段:prepare和commit/rollback。

????????2PC模型中,在prepare階段需要等待所有參與子事務(wù)的反饋,因此可能造成數(shù)據(jù)庫(kù)資源鎖定時(shí)間過(guò)長(zhǎng),不適合并發(fā)高以及子事務(wù)生命周長(zhǎng)較長(zhǎng)的業(yè)務(wù)場(chǎng)景。兩階段提交這種解決方案屬于犧牲了一部分可用性來(lái)?yè)Q取的一致性。
補(bǔ)償事務(wù)(TCC)
TCC 其實(shí)就是采用的補(bǔ)償機(jī)制,其核心思想是:針對(duì)每個(gè)操作,都要注冊(cè)一個(gè)與其對(duì)應(yīng)的確認(rèn)和補(bǔ)償(撤銷)操作。TCC模型是把鎖的粒度完全交給業(yè)務(wù)處理。它分為三個(gè)階段:
Try 階段主要是對(duì)業(yè)務(wù)系統(tǒng)做檢測(cè)及資源預(yù)留
Confirm 階段主要是對(duì)業(yè)務(wù)系統(tǒng)做確認(rèn)提交,Try階段執(zhí)行成功并開(kāi)始執(zhí)行 Confirm階段時(shí),默認(rèn) Confirm階段是不會(huì)出錯(cuò)的。即:只要Try成功,Confirm一定成功。
Cancel 階段主要是在業(yè)務(wù)執(zhí)行錯(cuò)誤,需要回滾的狀態(tài)下執(zhí)行的業(yè)務(wù)取消,預(yù)留資源釋放。

匯款服務(wù)和收款服務(wù)分別需要實(shí)現(xiàn),Try-Confirm-Cancel接口,并在業(yè)務(wù)初始化階段將其注入到TCC事務(wù)管理器中。、

由此可以看出,TCC模型對(duì)業(yè)務(wù)的侵入強(qiáng),改造的難度大。
本地消息表(異步確保)
本地消息表這種實(shí)現(xiàn)方式應(yīng)該是業(yè)界使用最多的,其核心思想是將分布式事務(wù)拆分成本地事務(wù)進(jìn)行處理,這種思路是來(lái)源于ebay。我們可以從下面的流程圖中看出其中的一些細(xì)節(jié):

基本思路就是:
????????消息生產(chǎn)方,需要額外建一個(gè)消息表,并記錄消息發(fā)送狀態(tài)。消息表和業(yè)務(wù)數(shù)據(jù)要在一個(gè)事務(wù)里提交,也就是說(shuō)他們要在一個(gè)數(shù)據(jù)庫(kù)里面。然后消息會(huì)經(jīng)過(guò)MQ發(fā)送到消息的消費(fèi)方。如果消息發(fā)送失敗,會(huì)進(jìn)行重試發(fā)送。
????????消息消費(fèi)方,需要處理這個(gè)消息,并完成自己的業(yè)務(wù)邏輯。此時(shí)如果本地事務(wù)處理成功,表明已經(jīng)處理成功了,如果處理失敗,那么就會(huì)重試執(zhí)行。如果是業(yè)務(wù)上面的失敗,可以給生產(chǎn)方發(fā)送一個(gè)業(yè)務(wù)補(bǔ)償消息,通知生產(chǎn)方進(jìn)行回滾等操作。
????????生產(chǎn)方和消費(fèi)方定時(shí)掃描本地消息表,把還沒(méi)處理完成的消息或者失敗的消息再發(fā)送一遍。如果有靠譜的自動(dòng)對(duì)賬補(bǔ)賬邏輯,這種方案還是非常實(shí)用的。
盡最大努力通知
? ??????最大努力通知方案主要也是借助MQ消息系統(tǒng)來(lái)進(jìn)行事務(wù)控制,這一點(diǎn)與可靠消息最終一致方案一樣??磥?lái)MQ中間件確實(shí)在一個(gè)分布式系統(tǒng)架構(gòu)中,扮演者重要的角色。最大努力通知方案是比較簡(jiǎn)單的分布式事務(wù)方案,它本質(zhì)上就是通過(guò)定期校對(duì),實(shí)現(xiàn)數(shù)據(jù)一致性。
最大努力通知方案的實(shí)現(xiàn)
業(yè)務(wù)活動(dòng)的主動(dòng)方,在完成業(yè)務(wù)處理之后,向業(yè)務(wù)活動(dòng)的被動(dòng)方發(fā)送消息,允許消息丟失。
主動(dòng)方可以設(shè)置時(shí)間階梯型通知規(guī)則,在通知失敗后按規(guī)則重復(fù)通知,直到通知N次后不再通知。
主動(dòng)方提供校對(duì)查詢接口給被動(dòng)方按需校對(duì)查詢,用于恢復(fù)丟失的業(yè)務(wù)消息。
業(yè)務(wù)活動(dòng)的被動(dòng)方如果正常接收了數(shù)據(jù),就正常返回響應(yīng),并結(jié)束事務(wù)。
如果被動(dòng)方?jīng)]有正常接收,根據(jù)定時(shí)策略,向業(yè)務(wù)活動(dòng)主動(dòng)方查詢,恢復(fù)丟失的業(yè)務(wù)消息
最大努力通知方案的特點(diǎn)
1、用到的服務(wù)模式:可查詢操作、冪等操作。
2、被動(dòng)方的處理結(jié)果不影響主動(dòng)方的處理結(jié)果;
3、適用于對(duì)業(yè)務(wù)最終一致性的時(shí)間敏感度低的系統(tǒng);
4、適合跨企業(yè)的系統(tǒng)間的操作,或者企業(yè)內(nèi)部比較獨(dú)立的系統(tǒng)間的操作,比如銀行通知、商戶通知等;

案例:
eBay 本地消息表
本地消息表這種實(shí)現(xiàn)方式的思路,其實(shí)是源于ebay,后來(lái)通過(guò)支付寶等公司的布道,在業(yè)內(nèi)廣泛使用。其基本的設(shè)計(jì)思想是將遠(yuǎn)程分布式事務(wù)拆分成一系列的本地事務(wù)。如果不考慮性能及設(shè)計(jì)優(yōu)雅,借助關(guān)系型數(shù)據(jù)庫(kù)中的表即可實(shí)現(xiàn)。
舉個(gè)經(jīng)典的跨行轉(zhuǎn)賬的例子來(lái)描述。第一步,扣款1W,通過(guò)本地事務(wù)保證了憑證消息插入到消息表中。第二步,通知對(duì)方銀行賬戶上加1W了。那問(wèn)題來(lái)了,如何通知到對(duì)方呢?
通常采用兩種方式:
采用時(shí)效性高的MQ,由對(duì)方訂閱消息并監(jiān)聽(tīng),有消息時(shí)自動(dòng)觸發(fā)事件
采用定時(shí)輪詢掃描的方式,去檢查消息表的數(shù)據(jù)。
類似使用本地消息表+消息通知的還有去哪兒,蘑菇街
各種第三方支付回調(diào)
最大努力通知型。如支付寶、微信的支付回調(diào)接口方式,不斷回調(diào)直至成功,或直至調(diào)用次數(shù)衰減至失敗狀態(tài)。
我們可以怎么來(lái)做
2PC/3PC需要資源管理器(mysql, redis)支持XA協(xié)議,且整個(gè)事務(wù)的執(zhí)行期間需要鎖住事務(wù)資源,會(huì)降低性能。故先排除。
TCC的模式,需要事務(wù)接口提供try,confirm,cancel三個(gè)接口,提高了編程的復(fù)雜性。需要依賴于業(yè)務(wù)方來(lái)配合提供這樣的接口。推行難度大,暫時(shí)排除。
最大努力通知型,應(yīng)用于異構(gòu)或者服務(wù)平臺(tái)當(dāng)中
可以看到ebay的經(jīng)典模式中,分布式的事務(wù),是通過(guò)本地事務(wù)+可靠消息,來(lái)達(dá)到事務(wù)的最終一致性的。但是出現(xiàn)了事務(wù)消息,就把本地事務(wù)的工作給涵蓋在事務(wù)消息當(dāng)中了。所以,接下來(lái)要基于事務(wù)消息來(lái)套我們的應(yīng)用場(chǎng)景,看起是否滿足我們對(duì)分布式事務(wù)產(chǎn)品的要求。