1. 程式人生 > >二階段提交與三階段提交

二階段提交與三階段提交

前面幾篇部落格中提到了CAP原理,以及CAP的幾種組合,比如符合AP的有Gossip協議;符合CP的有Paxos協議;符合CA的有二階段提交(2PC). 這篇文章就來介紹下二階段提交和有所改進的三階段提交。

二階段提交(2PC)

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

第一階段:準備階段
第二階段:提交階段

第一階段:準備階段

事務協調者(事務管理器)給每個參與者(資源管理器)傳送Prepare訊息,每個參與者要麼直接返回失敗(如許可權驗證失敗),要麼在本地執行事務,但不提交,達到一種“萬事俱備,只欠東風”的狀態。

具體分為3個步驟:
1.1 協調者詢問所有參與者是否可以執行提交操作(vote),並等待各參與者的響應。
1.2 參與者執行事務操作,但沒有提交(即沒有commit)
1.3 各參與者響應協調者的詢問。如果參與者的事務操作執行成功,則返回”同意”;如果參與者的事務操作執行失敗,則返回”中止”。

第二階段:提交階段

如果協調者收到了任一參與者的失敗訊息或者超時,則給每個參與者傳送回滾(Rollback)訊息;否則,傳送提交(Commit)訊息。
參與者根據協調者的指令執行提交或回滾操作,釋放所有事務處理過程中使用的鎖資源。(注意:必須在最後階段釋放鎖資源)

兩階段提交(2PC)的幾個缺點

  1. 同步阻塞問題
    執行過程中,所有參與這節點都是事務阻塞型的。當參與者佔有公共資源時,其他第三方節點訪問公共資源不得不處於阻塞狀態。

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

  3. 資料不一致
    在階段二,當協調者向參與者傳送commit請求之後,發生了網路異常,這將導致只有部分參與者收到了commit請求。這部分參與者接到commit請求之後就會執行commit操作,但是其他未接到commit請求的參與者則無法執行事務提交,於是整個分散式系統便出現了資料不一致的問題。

  4. 二階段無法解決的問題
    協調者在發出commit訊息之後宕機,而唯一接收到這條訊息的參與者同時也宕機了。那麼即使協調者通過選舉協議產生了新的協調者,這條事務的狀態也是不確定的,沒人知道事務是否被已經提交。

三階段提交

由於二階段提交存在以上諸多問題,所以研究者們在二階段提交的基礎上做了改進,提出了三階段提交。

三階段提交有2個改動:

  1. 在協調者和參與者中都引入了超時機制。
  2. 在第一階段和第二階段中插入一個準備階段。保證了在最後提交階段之前各參與節點的狀態是一致的。

三階段提交分為三個階段: CanCommit、PreCommit、DoCommit

1. CanCommit階段

協調者向參與者傳送commit請求,參與者如果可以提交就返回Yes,否則返回No.

  1. 事務詢問
    協調者向參與者傳送CanCommit請求,詢問是否可以執行事務提交操作,並進入等待

  2. 響應反饋
    參與者接到CanCommit請求之後,如果認為可以順利執行事務,則返回Yes,並進入預備狀態;否則反饋No

2. PreCommit階段

協調者根據參與者的響應來決定是否可以繼續事務的PreCommit操作。根據響應情況,有以下2種可能: 事務預執行 或 中斷事務

2.1 假如協調者從所有的參與者獲得的反饋都是Yes響應,那麼就會執行事務的預執行。

  1. 傳送預提交請求
    協調者向參與者傳送PreCommit請求,並進入Prepared階段。

  2. 事務預執行
    參與者接收到PreCommit請求後,會執行事務操作

  3. 響應反饋
    如果參與者成功執行了事務操作,則返回ACK響應,同時開始等待最終指令。

2.2 假如有任何一個參與者向協調者傳送了No響應或等待超時,那麼就執行事務的中斷

  1. 傳送中斷請求
    協調者向所有參與者傳送abort請求。

  2. 中斷事務
    參與者收到來自協調者的abort請求之後(或超時之後,仍未收到協調者的請求),執行事務的中斷。

3. DoCommit階段

該階段進行真正的事務提交,也可以分為以下兩種情況: 執行提交 或 中斷事務

3.1 執行提交

  1. 傳送提交請求
    協調者接收到參與者傳送的ACK響應,那麼它將從預提交狀態進入到提交狀態。並向所有參與者傳送DoCommit請求。

  2. 事務提交
    參與者接收到DoCommit請求之後,執行正式的事務提交;並在完成事務提交之後釋放所有事務資源。

  3. 響應反饋
    事務提交完之後,向協調者傳送Ack響應。

  4. 完成事務
    協調者接收到所有參與者的Ack響應之後,完成事務。

3.2 中斷事務
協調者沒有接收到參與者傳送的ACK響應(不是ACK或超時),那麼就執行中斷事務。

1.傳送中斷請求
協調者向所有參與者傳送abort請求

2.事務回滾
參與者接收到abort請求之後,利用其在階段二記錄的undo資訊來執行事務的回滾操作,並在完成回滾之後釋放所有的事務資源。

3.反饋結果
參與者完成事務回滾之後,向協調者傳送ACK訊息

4.中斷事務
協調者接收到參與者反饋的ACK訊息之後,執行事務的中斷。

在DoCommit階段,如果參與者無法及時接收到來自協調者的DoCommit或者abort請求,則在等待超時之後,會繼續進行事務的提交。

2PC與3PC的區別

相對於2PC,3PC主要解決單點故障問題,並減少阻塞(一旦參與者無法及時收到來自協調者的資訊之後,他會預設執行commit,而不會一直持有事務資源並處於阻塞狀態)。
但是3PC也有資料一致性問題: 比如,由於網路原因,協調者傳送的abort響應沒有及時被參與者接收到,那麼參與者在等待超時之後執行了commit操作,這樣就和其他接到abort命令並執行回滾的參與者之間存在資料不一致了。

(完)