兩階段提交(2PC) 是 Oracle Tuxedo 系統(tǒng)提出的 XA 分布式事務(wù)協(xié)議的其中一種實(shí)現(xiàn)方式六孵。
一、關(guān)于 XA 分布式事務(wù)協(xié)議
XA 分布式協(xié)議主要有兩個(gè)角色:
- 事務(wù)管理器(協(xié)調(diào)者)
事務(wù)管理器作為全局事務(wù)的協(xié)調(diào)管理者太援,與每個(gè)資源管理器通信闽晦,完成分布式事務(wù)的管理。 - 資源管理器 (參與者)
資源管理器管理每個(gè)參與者的事務(wù)資源粉寞,其應(yīng)該具有提交和回滾的能力尼荆,如數(shù)據(jù)庫。
XA 分布式協(xié)議制定的分段提交過程:
- 第一階段( prepare )
第一階段每個(gè)參與者準(zhǔn)備執(zhí)行事務(wù)并對(duì)需要的資源加鎖唧垦,進(jìn)入 ready 狀態(tài),并通知協(xié)調(diào)者已經(jīng)準(zhǔn)備就緒液样。 - 第二階段( commit )
第二階段當(dāng)協(xié)調(diào)者確認(rèn)每個(gè)參與者都 ready 后振亮,通知參與者進(jìn)行 commit 操作;如果有參與者 fail 鞭莽,則發(fā)送 rollback 命令坊秸,各參與者做回滾。
二澎怒、兩階段提交( 2PC )
基于 XA 協(xié)議褒搔,有了兩階段提交的實(shí)現(xiàn),在 JAVA 中可以使用基于兩階段提交的 atomikos 來進(jìn)行分布式事務(wù)管理喷面。
理解起來其實(shí)很簡單星瘾,下面就從 2PC 的不同階段和不同的狀態(tài)來分析它的執(zhí)行過程:
第一階段
-
各參與者都成功的情況
- 首先事務(wù)協(xié)調(diào)者向所有參與者發(fā)送 prepare 請求。
- 參與者開始執(zhí)行各自的數(shù)據(jù)更新惧辈,寫入各自的 Undo Log 和 Redo Log琳状。
- 參與者執(zhí)行成功后,暫時(shí)不提交事務(wù)盒齿,向協(xié)調(diào)者發(fā)送 Done 消息念逞。
- 進(jìn)入第二階段困食。
-
有參與者失敗的情況
在第一階段,如果參與者在本地事務(wù)中執(zhí)行失敗翎承,會(huì)向協(xié)調(diào)者發(fā)送 Fail 消息硕盹,協(xié)調(diào)者產(chǎn)生事務(wù)中斷。
事務(wù)中斷
任何一個(gè)參與者向協(xié)調(diào)者反饋了 Fail 消息叨咖,或者在等待超時(shí)之后莱睁,協(xié)調(diào)者不能接收到參與者的反饋響應(yīng),就會(huì)中斷事務(wù)芒澜。
步驟如下:
- 協(xié)調(diào)者向所有參與者發(fā)出 Rollback 請求仰剿。
- 參與者收到 Rollback 請求之后,會(huì)利用其在階段一種記錄的 Undo 信息來執(zhí)行事務(wù)回滾操作痴晦,并在完成回滾之后釋放在整個(gè)事物執(zhí)行期間占用的資源南吮。
- 參與者在完成事物回滾之后,向協(xié)調(diào)者發(fā)送 Ack 消息誊酌。
- 中斷事務(wù)
第二階段
第二階段中部凑,如果所有參與者的都執(zhí)行成功,則協(xié)調(diào)者下發(fā) Commit 消息涂邀,參與者提交本地事務(wù),釋放鎖住的資源箱锐,并向協(xié)調(diào)者發(fā)送 Ack 確認(rèn)。
當(dāng)協(xié)調(diào)者受到所有的參與者確認(rèn)消息后驹止,整個(gè)分布式事務(wù)結(jié)束浩聋。
三臊恋、總結(jié)
基于以上,可以很容易理解 2PC 的執(zhí)行過程抖仅,同時(shí)我們也注意到它存在的缺點(diǎn):
- 對(duì)高并發(fā)不友好坊夫。
在分布式事務(wù)的執(zhí)行過程中撤卢,存在多次通信,占用時(shí)間長凸丸,并且在這個(gè)過程中所有節(jié)點(diǎn)處于阻塞狀態(tài),每個(gè)參與者持有的資源始終要加鎖屎慢。- 單點(diǎn)故障瞭稼。由上面可知協(xié)調(diào)者扮演著非常重要的角色,一旦協(xié)調(diào)者發(fā)生故障环肘,參與者就會(huì)一直阻塞下去欲虚。尤其在第二階段悔雹,協(xié)調(diào)者發(fā)生故障复哆,那么所有的參與者還都處于鎖定事務(wù)資源的狀態(tài)中,而無法繼續(xù)完成事務(wù)操作腌零。
- 數(shù)據(jù)不一致梯找。在第二階段中,當(dāng)協(xié)調(diào)者向參與者發(fā)送 commit 請求之后益涧,發(fā)生了局部網(wǎng)絡(luò)異承獯福或者在發(fā)送 commit 請求過程中協(xié)調(diào)者發(fā)生了故障,就會(huì)導(dǎo)致只有一部分參與者接受到了commit 請求闲询。而在這部分參與者接到 commit 請求之后就會(huì)執(zhí)行 commit 操作久免,但是其他未接到 commit 請求的機(jī)器則無法執(zhí)行事務(wù)提交,就導(dǎo)致了數(shù)據(jù)的不一致扭弧。
歡迎訪問個(gè)人博客 獲取更多知識(shí)分享阎姥。