分散式事務之兩階段提交 (2PC)
1. 概述
在計算機網路以及資料庫領域內,二階段提交( Two-phase Commit
)是指,為了使基於分散式系統架構下的 所有節點在進行事務提交時保持一致性
而設計的一種演算法。通常,二階段提交也被稱為是一種協議。在分散式系統中,雖然每個節點可以知道自己的操作是成功還是失敗,但卻無法知道其他節點的操作是成功還是失敗。當一個事務跨越多個節點時,為了保持事務的ACID特性,需要引入一個作為協調者的元件來統一協調所有節點(稱作參與者)的操作結果並最終指示這些節點是否要把操作結果進行真正的提交(比如將更新後的資料寫入磁碟等等)。因此,二階段提交的演算法思路可以概括為: 參與者將操作成敗通知協調者,再由協調者根據所有參與者的反饋情況決定各參與者是否要提交操作還是中止操作。
2. 前提
二階段提交演算法的成立基於以下假設:
-
分散式系統中,存在一個節點作為協調者,其他節點作為參與者。且節點之間可以進行網路通訊。
-
所有節點都採用預寫式日誌,且日誌被寫入後即被保持在可靠的儲存裝置上,即使節點損壞也不會導致日誌資料的消失。
-
所有節點不會永久性損壞,即使損壞後仍然可以恢復。
3. 兩階段提交
所謂的兩個階段是指:第一階段的提交請求階段(投票階段)和第二階段的提交階段(完成階段)。
3.1 第一階段:提交請求階段
可以進一步將提交請求階段分為以下三個步驟:
-
協調者節點向所有參與者節點詢問是否可以執行提交操作,並開始等待各參與者節點的響應。
-
參與者節點執行詢問發起為止的所有事務操作,並將Undo資訊和Redo資訊寫入日誌。
-
各參與者節點返回協調者節點發起詢問的響應。如果參與者節點的事務操作實際執行成功,則它返回一個”同意”訊息;如果參與者節點的事務操作實際執行失敗,則它返回一個”中止”訊息。
有時候,第一階段也被稱作投票階段,即各參與者投票是否要繼續接下來的提交操作。
3.2 第二階段:提交執行階段
如果協調者從所有參與者節點獲得的相應訊息都為”同意”,則向所有參與者節點發出”正式提交”的請求,否則發出”回滾操作”的請求。參與者根據協調者的指令執行提交或者回滾操作,釋放所有事務處理過程中使用的鎖資源。
(1) 當協調者節點從所有參與者節點獲得的相應訊息都為”同意”時(成功):
-
協調者節點向所有參與者節點發出”正式提交”的請求。
-
參與者節點正式完成操作,並釋放在整個事務期間內佔用的資源。
-
參與者節點向協調者節點發送”完成”訊息。
-
協調者節點收到所有參與者節點反饋的”完成”訊息後,完成事務。
(2) 如果任一參與者節點在第一階段返回的響應訊息為”終止”,或者協調者節點在第一階段的詢問超時之前無法獲取所有參與者節點的響應訊息時(失敗):
-
協調者節點向所有參與者節點發出”回滾操作”的請求。
-
參與者節點利用之前寫入的Undo資訊執行回滾,並釋放在整個事務期間內佔用的資源。
-
參與者節點向協調者節點發送”回滾完成”訊息。
-
協調者節點收到所有參與者節點反饋的”回滾完成”訊息後,取消事務。
有時候,第二階段也被稱作完成階段,因為無論結果怎樣,協調者都必須在此階段結束當前事務。
4. 缺點
(1) 同步阻塞:兩階段提交的最大缺點就在於它的執行過程中間節點都處於阻塞狀態。即節點之間在等待對方的相應訊息時,它將什麼也做不了。特別是,當一個節點在已經佔有了某項資源的情況下,為了等待其他節點的響應訊息而陷入阻塞狀態時,當第三個節點嘗試訪問該節點佔有的資源時,這個節點也將連帶陷入阻塞狀態。
(2) 超時機制:協調者節點指示參與者節點進行提交等操作時,如有參與者節點出現了崩潰等情況而導致協調者始終無法獲取所有參與者的響應資訊,這時協調者將只能依賴協調者自身的超時機制來處理。但往往超時機制處理時,協調者都會指示參與者進行回滾操作。這樣的策略顯得比較保守。
(3) 單點故障:由於協調者的重要性,一旦協調者發生故障。參與者會一直阻塞下去。尤其在第二階段,協調者發生故障,那麼所有的參與者都處於鎖定事務資源的狀態中,而無法繼續完成事務操作。(如果是協調者掛掉,可以重新選舉一個協調者,但是無法解決因為協調者宕機導致的參與者處於阻塞狀態的問題)
(4) 資料不一致:在第二階段中,當協調者向參與者傳送提交請求之後,如果發生了局部網路異常或者在傳送提交請求過程中協調者發生了故障,這會導致只有一部分參與者接受到了提交請求。而在這部分參與者接到提交請求之後就會執行提交操作。但是其他未接到提交請求的機器則無法執行事務提交。於是整個分散式系統便出現了資料不一致性的現象。