在上一篇文章中,我們已經(jīng)了解了分布式事務(wù)的定義,本文我們將了解常用的分布式事務(wù)解決方案。關(guān)注我的公眾號(hào)「Java面典」帅容,每天 10:24 和你一起了解更多 Java 相關(guān)知識(shí)點(diǎn)。
二階段提交
二階段提交(Two-phaseCommit)是指伍伤,在計(jì)算機(jī)網(wǎng)絡(luò)以及數(shù)據(jù)庫(kù)領(lǐng)域內(nèi)并徘,為了使基于分布式系統(tǒng)架構(gòu)下的所有節(jié)點(diǎn)在進(jìn)行事務(wù)提交時(shí)保持一致性而設(shè)計(jì)的一種算法(Algorithm)。通常扰魂,二階段提交也被稱為是一種協(xié)議(Protocol))麦乞。
在分布式系統(tǒng)中,每個(gè)節(jié)點(diǎn)雖然可以知曉自己的操作時(shí)成功或者失敗劝评,卻無(wú)法知道其他節(jié)點(diǎn)的操作的成功或失敗姐直。當(dāng)一個(gè)事務(wù)跨越多個(gè)節(jié)點(diǎn)時(shí),為了保持事務(wù)的 ACID 特性蒋畜,需要引入一個(gè)作為協(xié)調(diào)者的組件來(lái)統(tǒng)一掌控所有節(jié)點(diǎn)(稱作參與者)的操作結(jié)果声畏,并最終指示這些節(jié)點(diǎn)是否要把操作結(jié)果進(jìn)行真正的提交(比如將更新后的數(shù)據(jù)寫入磁盤等等)。
二階段提交的算法思路可以概括為:參與者將操作成敗通知協(xié)調(diào)者姻成,再由協(xié)調(diào)者根據(jù)所有參與者的反饋情報(bào)決定各參與者是否要提交操作還是中止操作插龄。
實(shí)現(xiàn)
準(zhǔn)備階段:事務(wù)協(xié)調(diào)者(事務(wù)管理器)給每個(gè)參與者(資源管理器))發(fā)送 Prepare 消息,每個(gè)參與者要么直接返回失斂普埂(如權(quán)限驗(yàn)證失斁巍),要么在本地執(zhí)行事務(wù)才睹,寫本地的 redo 和 undo 日志徘跪,但不提交。
提交階段:如果協(xié)調(diào)者收到了參與者的失敗消息或者超時(shí)琅攘,直接給每個(gè)參與者發(fā)送回滾(Rollback)消息真椿;否則,發(fā)送提交(Commit)消息乎澄;參與者根據(jù)協(xié)調(diào)者的指令執(zhí)行提交或者回滾操作突硝,釋放所有事務(wù)處理過(guò)程中使用的鎖資源(注意:必須在最后階段釋放鎖資源)。
缺點(diǎn)
同步阻塞問(wèn)題:執(zhí)行過(guò)程中置济,所有參與節(jié)點(diǎn)都是事務(wù)阻塞型的解恰;
單點(diǎn)故障:由于協(xié)調(diào)者的重要性,一旦協(xié)調(diào)者發(fā)生故障浙于。參與者會(huì)一直阻塞下去护盈;
數(shù)據(jù)不一致(腦裂問(wèn)題):在二階段提交的階段二中,當(dāng)協(xié)調(diào)者向參與者發(fā)送 commit 請(qǐng)求之后羞酗,發(fā)生了局部網(wǎng)絡(luò)異掣危或者在發(fā)送 commit 請(qǐng)求過(guò)程中協(xié)調(diào)者發(fā)生了故障,導(dǎo)致只有一部分參與者接受到了 commit 請(qǐng)求。于是整個(gè)分布式系統(tǒng)便出現(xiàn)了數(shù)據(jù)部一致性的現(xiàn)象(腦裂現(xiàn)象)胸竞;
二階段無(wú)法解決的問(wèn)題(數(shù)據(jù)狀態(tài)不確定):協(xié)調(diào)者再發(fā)出 commit 消息之后宕機(jī)欺嗤,而唯一接收到這條消息的參與者同時(shí)也宕機(jī)了。那么即使協(xié)調(diào)者通過(guò)選舉協(xié)議產(chǎn)生了新的協(xié)調(diào)者卫枝,這條事務(wù)的狀態(tài)也是不確定的煎饼,沒(méi)人知道事務(wù)是否被已經(jīng)提交。
三階段提交
三階段提交( Three-phase commit ) 校赤, 也 叫 三 階 段 提 交 協(xié) 議 ( Three-phase commit protocol)吆玖,是二階段提交(2PC)的改進(jìn)版本。
與兩階段提交不同的是马篮,三階段提交有兩個(gè)改動(dòng)點(diǎn):
引入超時(shí)機(jī)制沾乘。同時(shí)在協(xié)調(diào)者和參與者中都引入超時(shí)機(jī)制;
在第一階段和第二階段中插入一個(gè)準(zhǔn)備階段浑测。保證了在最后提交階段之前各參與節(jié)點(diǎn)的狀態(tài)是一致的意鲸。也就是說(shuō),除了引入超時(shí)機(jī)制之外尽爆,3PC 把 2PC 的準(zhǔn)備階段再次一分為二怎顾,這樣三階段提交就有 CanCommit、PreCommit漱贱、DoCommit 三個(gè)階段槐雾。
實(shí)現(xiàn)
CanCommit 階段:協(xié)調(diào)者向參與者發(fā)送 commit 請(qǐng)求,參與者如果可以提交就返回 Yes 響應(yīng)幅狮,否則返回 No 響應(yīng)募强;
PreCommit 階段:協(xié)調(diào)者根據(jù)參與者的反應(yīng)情況來(lái)決定是否可以繼續(xù)進(jìn)行,有以下兩種可能崇摄。假如協(xié)調(diào)者從所有的參與者獲得的反饋都是 Yes 響應(yīng)擎值,那么就會(huì)執(zhí)行事務(wù)的預(yù)執(zhí)行假如有任何一個(gè)參與者向協(xié)調(diào)者發(fā)送了 No 響應(yīng),或者等待超時(shí)之后逐抑,協(xié)調(diào)者都沒(méi)有接到參與者的響應(yīng)鸠儿,那么就執(zhí)行事務(wù)的中斷;
DoCommit 階段:該階段進(jìn)行真正的事務(wù)提交厕氨,主要包含:
1). 協(xié)調(diào)者發(fā)送提交請(qǐng)求进每;
2). 參與者提交事務(wù);
3). 參與者響應(yīng)反饋( 事務(wù)提交完之后命斧,向協(xié)調(diào)者發(fā)送 Ack 響應(yīng)田晚。)
4). 協(xié)調(diào)者確定完成事務(wù)。
柔性事務(wù)
在電商領(lǐng)域等互聯(lián)網(wǎng)場(chǎng)景下国葬,傳統(tǒng)的事務(wù)在數(shù)據(jù)庫(kù)性能和處理能力上都暴露出了瓶頸贤徒。在分布式領(lǐng)域基于 CAP 理論以及 BASE 理論芹壕,有人就提出了 柔性事務(wù) 的概念。CAP(一致性接奈、可用性踢涌、分區(qū)容忍性)理論大家都理解很多次了,這里不再敘述鲫趁。說(shuō)一下 BASE 理論斯嚎,它是在 CAP 理論的基礎(chǔ)之上的延伸利虫。包括 基本可用(Basically Available)挨厚、柔性狀態(tài)(Soft State)、最終一致性(Eventual Consistency)糠惫。通常所說(shuō)的柔性事務(wù)分為:兩階段型疫剃、補(bǔ)償型、異步確保型硼讽、最大努力通知型幾種巢价。
兩階段型
就是分布式事務(wù)兩階段提交,對(duì)應(yīng)技術(shù)上的 XA固阁、JTA/JTS壤躲。這是分布式環(huán)境下事務(wù)處理的
典型模式。
補(bǔ)償型
TCC 型事務(wù)(Try/Confirm/Cancel)可以歸為補(bǔ)償型备燃。
WS-BusinessActivity 提供了一種基于補(bǔ)償?shù)?long-running 的事務(wù)處理模型碉克。服務(wù)器 A 發(fā)起事務(wù),服務(wù)器 B 參與事務(wù)并齐,服務(wù)器 A 的事務(wù)如果執(zhí)行順利漏麦,那么事務(wù) A 就先行提交,如果事務(wù) B 也執(zhí)行順利况褪,則事務(wù) B 也提交撕贞,整個(gè)事務(wù)就算完成。但是如果事務(wù) B 執(zhí)行失敗测垛,事務(wù) B 本身回滾捏膨,這時(shí)事務(wù) A 已經(jīng)被提交,所以需要執(zhí)行一個(gè)補(bǔ)償操作食侮,將已經(jīng)提交的事務(wù) A 執(zhí)行的操作作反操作脊奋,恢復(fù)到未執(zhí)行前事務(wù) A 的狀態(tài)。這樣的 SAGA 事務(wù)模型疙描,是犧牲了一定的隔離性和一致性的诚隙,但是提高了 long-running 事務(wù)的可用性。
異步確保型
通過(guò)將一系列同步的事務(wù)操作變?yōu)榛谙?zhí)行的異步操作, 避免了分布式事務(wù)中的同步
阻塞操作的影響起胰。
最大努力通知型(多次嘗試)
這是分布式事務(wù)中要求最低的一種, 也可以通過(guò)消息中間件實(shí)現(xiàn), 與前面異步確保型操作不同的一點(diǎn)是, 在消息由 MQ Server 投遞到消費(fèi)者之后, 允許在達(dá)到最大重試次數(shù)之后正常結(jié)束事務(wù)久又。