分佈式事務2PC && 3PC

二階段提交(Two-phase Commit)是指,爲了使基於分佈式系統架構下的所有節點在進行事務提交時保持一致性而設計的一種算法(Algorithm)。通常,二階段提交也被稱爲是一種協議(Protocol)…

在分佈式系統中,每個節點雖然可以知曉自己的操作時成功或者失敗,卻無法知道其他節點的操作的成功或失敗。當一個事務跨越多個節點時,爲了保持事務的ACID特性,需要引入一個作爲協調者的組件來統一掌控所有節點(稱作參與者)的操作結果並最終指示這些節點是否要把操作結果進行真正的提交(比如將更新後的數據寫入磁盤等等)。因此,二階段提交的算法思路可以概括爲: 參與者將操作成敗通知協調者,再由協調者根據所有參與者的反饋情報決定各參與者是否要提交操作還是中止操作。 (from Wikipedia)

2PC

  • 階段1:請求階段(commit-request phase,或稱表決階段,voting phase)

  • 協調者節點向所有參與者節點詢問是否可以執行提交操作,並開始等待各參與者節點的響應。

  • 參與者節點執行詢問發起爲止的所有事務操作,並將Undo信息和Redo信息寫入日誌。

  • 各參與者節點響應協調者節點發起的詢問。如果參與者節點的事務操作實際執行成功,則它返回一個”同意”消息;如果參與者節點的事務操作實際執行失敗,則它返回一個”中止”消息。 有時候,第一階段也被稱作投票階段,即各參與者投票是否要繼續接下來的提交操作。。

  • 階段2:提交階段(commit phase)

在該階段,協調者將基於第一個階段的投票結果進行決策:提交或取消。當且僅當所有的參與者同意提交事務協調者才通知所有的參與者提交事務,否則協調者將通知所有的參與者取消事務。參與者在接收到協調者發來的消息後將執行響應的操作。

成功

    

  1. 當協調者節點從所有參與者節點獲得的相應消息都爲”同意”時:
  2. 協調者節點向所有參與者節點發出”正式提交”的請求。
  3. 參與者節點正式完成操作,並釋放在整個事務期間內佔用的資源。
  4. 參與者節點向協調者節點發送”完成”消息。
  5. 協調者節點收到所有參與者節點反饋的”完成”消息後,完成事務。

失敗

    

  1. 如果任一參與者節點在第一階段返回的響應消息爲”終止”,或者 協調者節點在第一階段的詢問超時之前無法獲取所有參與者節點的響應消息時:
  2. 協調者節點向所有參與者節點發出”回滾操作”的請求。
  3. 參與者節點利用之前寫入的Undo信息執行回滾,並釋放在整個事務期間內佔用的資源。
  4. 參與者節點向協調者節點發送”回滾完成”消息。
  5. 協調者節點收到所有參與者節點反饋的”回滾完成”消息後,取消事務。

有時候,第二階段也被稱作完成階段,因爲無論結果怎樣,協調者都必須在此階段結束當前事務。

現實生活中其實很多地方都在使用 2PC :

組織者組織出遊,給每個參與者發送出遊確認郵件,每個參與者回覆去或是不去給組織者,如果都回復ok,那麼就可以出遊,要是有一個人回覆NO, 那麼這次出遊就取消(使用了2PC)

2PC 存在的問題

  • 同步阻塞問題

它的執行過程中間,節點都處於阻塞狀態。即節點之間在等待對方的相應消息時,它將什麼也做不了。特別是,當一個節點在已經佔有了某項資源的情況下,爲了等待其他節點的響應消息而陷入阻塞狀態時,當第三個節點嘗試訪問該節點佔有的資源時,這個節點也將連帶陷入阻塞狀態

  • 單點故障

由於協調者的重要性,一旦協調者發生故障。參與者會一直阻塞下去。尤其在第二階段,協調者發生故障,那麼所有的參與者還都處於鎖定事務資源的狀態中,而無法繼續完成事務操作。(如果是協調者掛掉,可以重新選舉一個協調者,但是無法解決因爲協調者宕機導致的參與者處於阻塞狀態的問題)

  • 數據不一致問題

  • 情形一: 協調者掛了,參與者沒掛(單點故障,不會造成數據不一致)

  • 情形二: 參與者掛了, 協調者沒掛(不會造成數據不一致)

    • 掛了的參與者不會恢復, 不會造成數據不一致
    • 掛了的參與者恢復過來,如果之前有未完成的事務,直接取消掉,然後詢問協調者目前我應該怎麼做,協調者就會比對自己的事務執行記錄和該參與者的事務執行記錄,告訴他應該怎麼做來保持數據的一致性
  • 參與者和協調者都掛了

    • 都在第一階段掛了, 參與者都沒有執行 commit, 在剩餘的參與者中重新選出一個協調者,新的協調者在重新詢問是 commit or roolback
    • 都在第二階段掛了, 掛了的參與者在掛掉之前沒有收到協調者的指令, 或者接到指令還沒有來得及進行 commit or roolback 操作,這種情形下,當新的協調者被選出來之後,他同樣是詢問所有的參與者的情況。只要有機器執行了abort(roolback)操作或者第一階段返回的信息是No的話,那就直接執行roolback操作。如果沒有人執行abort操作,但是有機器執行了commit操作,那麼就直接執行commit操作。這樣,當掛掉的參與者恢復之後,只要按照協調者的指示進行事務的commit還是roolback操作就可以了。因爲掛掉的機器並沒有做commit或者roolback操作,而沒有掛掉的機器們和新的協調者又執行了同樣的操作,那麼這種情況不會導致數據不一致現象。
    • 第二階段協調者和參與者掛了,掛了的這個參與者在掛之前已經執行了操作。但是由於他掛了,沒有人知道他執行了什麼操作。這種情況下,新的協調者被選出來之後,如果他想負起協調者的責任的話他就只能按照之前那種情況來執行commit或者roolback操作。這樣新的協調者和所有沒掛掉的參與者就保持了數據的一致性,我們假定他們執行了commit。但是,這個時候,那個掛掉的參與者恢復了怎麼辦,因爲他之前已經執行完了之前的事務,如果他執行的是commit那還好,和其他的機器保持一致了,萬一他執行的是roolback操作那?這不就導致數據的不一致性了麼?雖然這個時候可以再通過手段讓他和協調者通信,再想辦法把數據搞成一致的,但是,這段時間內他的數據狀態已經是不一致的了! 2PC 無法解決這個問題,這個問題有可能導致數據不一致的 ,於是就有了3PC(三階段提交)

3PC

三階段提交(英語:Three-phase commit),也叫三階段提交協議(英語:Three-phase commit protocol),是在計算機網絡及數據庫的範疇下,使得一個分佈式系統內的所有節點能夠執行事務的提交的一種分佈式算法。三階段提交是爲解決兩階段提交協議|的缺點而設計的。 與兩階段提交不同的是,三階段提交是“非阻塞”協議。三階段提交在兩階段提交的第一階段與第二階段之間插入了一個準備階段,使得原先在兩階段提交中,參與者在投票之後,由於協調者發生崩潰或錯誤,而導致參與者處於無法知曉是否提交或者中止的“不確定狀態”所產生的可能相當長的延時的問題[1]得以解決。 舉例來說,假設有一個決策小組由一個主持人負責與多位組員以電話聯絡方式協調是否通過一個提案,以兩階段提交來說,主持人收到一個提案請求,打電話跟每個組員詢問是否通過並統計回覆,然後將最後決定打電話通知各組員。要是主持人在跟第一位組員通完電話後失憶,而第一位組員在得知結果並執行後老人癡呆,那麼即使重新選出主持人,也沒人知道最後的提案決定是什麼,也許是通過,也許是駁回,不管大家選擇哪一種決定,都有可能與第一位組員已執行過的真實決定不一致,老闆就會不開心認爲決策小組溝通有問題而解僱。三階段提交即是引入了另一個步驟,主持人打電話跟組員通知請準備通過提案,以避免沒人知道真實決定而造成決定不一致的失業危機。爲什麼能夠解決二階段提交的問題呢?回到剛剛提到的狀況,在主持人通知完第一位組員請準備通過後兩人意外失憶,即使沒人知道全體在第一階段的決定爲何,全體決策組員仍可以重新協調過程或直接否決,不會有不一致決定而失業。那麼當主持人通知完全體組員請準備通過並得到大家的再次確定後進入第三階段,當主持人通知第一位組員請通過提案後兩人意外失憶,這時候其他組員再重新選出主持人後,仍可以知道目前至少是處於準備通過提案階段,表示第一階段大家都已經決定要通過了,此時便可以直接通過。(from Wikipedia)


存在的問題

在doCommit階段,如果參與者無法及時接收到來自協調者的doCommit或者rebort請求時,會在等待超時之後,會繼續進行事務的提交。 所以,由於網絡原因,協調者發送的abort響應沒有及時被參與者接收到,那麼參與者在等待超時之後執行了commit操作。這樣就和其他接到abort命令並執行回滾的參與者之間存在數據不一致的情況。

參考

  1. wikipedia
  2. 分佈式系統的事務處理
  3. 關於分佈式事務、兩階段提交協議、三階提交協議
  4. 深入理解分佈式系統的2PC和3PC
吃水不忘挖井人:原文鏈接:http://int64.me/2016/%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A12PC%20&&%203PC.html

發佈了72 篇原創文章 · 獲贊 54 · 訪問量 38萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章