一致性協議
基于CAP理論,在分布式系統設計過程中,系統的可用性和數據一致性需要我們反復的去權衡,于是就產生了很多經典的數據一致性協議,比如2PC、3PC, PAXOS等。
2PC協議
2PC是Two Phase Commit的縮寫,即兩階段提交。所謂的兩個階段是指:第一階段:準備階段(投票階段)和第二階段:提交階段(執行階段)。在分布式系統中,每個節點雖然可以知曉自己的操作時成功或者失敗,卻無法知道其他節點的操作的成功或失敗。當一個事務跨越多個節點時,為了保持事務的ACID特性,需要引入一個作為協調者的組件來統一掌控所有節點(稱作參與者)的操作結果并最終指示這些節點是否要把操作結果進行真正的提交(比如將更新后的數據寫入磁盤等等)。因此,二階段提交的算法思路可以概括為:參與者將操作成敗通知協調者,再由協調者根據所有參與者的反饋情報決定各參與者是否要提交操作還是中止操作。
協議說明
階段一:提交事務請求
- 事務詢問
協調者向所有的參與者發送事務內容,詢問是否可以執行事務提交操作,并開始等待各個響應者的反饋。 - 執行事務
各參與者執行事務操作,并將Undo和Redo信息記入事務日志中。 - 執行事務
各參與者向協調者反饋事務詢問的響應
如果參與者成功執行了事務操作,那么就反饋給協調者Yes響應,表示事務可以執行;如果參與者沒有成功執行事務,那么就反饋給協調者No響應,表示事務不可以執行。
階段二:執行事務提交
在階段二中,協調者會根據階段一中各參與者的反饋情況來決定最終是否可以進行事務的提交,主要包含以下兩種可能:
執行事務提交
假如協調者從所有的參與者得到的反饋全是Yes,那么協調者就會執行事務提交操作。
- 發送提交請求
協調者向所有的參與者發出Commit請求。 - 事務提交
參與者收到協調者的Commit請求后,會正式的執行事務提交操作,并在完成之后釋放執行事務期間占有的相關資源。 - 反饋事務提交結果
參與者在完成事務提交之后,向協調者發送Ack確認消息。 - 完成事務
協調者接收到所有參與者反饋的Ack消息后,完成事務。
執行事務提交
假如任何一個參與者向協調者反饋了No響應,或者在等待超時之后,協調者尚無收到所有參與者的反饋響應,那么協調者就會中斷事務。
- 發送回滾請求
協調者向所有的參與者發出Rollback請求。 - 事務回滾
參與者收到協調者的Rollback請求后,會利用在階段一中記錄的Undo信息來執行事務的回滾操作,并在回滾之后釋放占有的相關的資源會正式的執行事務提交操作,并在完成之后釋放執行事務期間占有的相關資源。 - 反饋事務回滾結果
參與者在完成事務回滾之后,向協調者發送Ack確認消息。 - 中斷事務
協調者接收到所有參與者反饋的Ack消息后,完成事務中斷。
2PC優缺點
優點就不用說了,原理簡單,實現起來比較容易;缺點還是需要詳細介紹下的,主要包含以下幾點:
- 同步阻塞問題。執行過程中,所有參與節點都是事務阻塞型的。當參與者占有公共資源時,其他第三方節點訪問公共資源不得不處于阻塞狀態。
- 單點故障。由于協調者的重要性,一旦協調者發生故障。參與者會一直阻塞下去。尤其在第二階段,協調者發生故障,那么所有的參與者還都處于鎖定事務資源的狀態中,而無法繼續完成事務操作。(如果是協調者掛掉,可以重新選舉一個協調者,但是無法解決因為協調者宕機導致的參與者處于阻塞狀態的問題)
- 數據不一致。在二階段提交的階段二中,當協調者向參與者發送commit請求之后,發生了局部網絡異常或者在發送commit請求過程中協調者發生了故障,這回導致只有一部分參與者接受到了commit請求。而在這部分參與者接到commit請求之后就會執行commit操作。但是其他部分未接到commit請求的機器則無法執行事務提交。于是整個分布式系統便出現了數據部一致性的現象。
- 二階段無法解決的問題:協調者再發出commit消息之后宕機,而唯一接收到這條消息的參與者同時也宕機了。那么即使協調者通過選舉協議產生了新的協調者,這條事務的狀態也是不確定的,沒人知道事務是否被已經提交。
3PC協議
三階段提交(Three-phase commit),也叫三階段提交協議(Three-phase commit protocol),是二階段提交(2PC)的改進版本。與兩階段提交不同的是,三階段提交有兩個改動點:
- 引入超時機制。同時在協調者和參與者中都引入超時機制。
- 在第一階段和第二階段中插入一個準備階段。保證了在最后提交階段之前各參與節點的狀態是一致的。
也就是說,除了引入超時機制之外,3PC把2PC的準備階段再次一分為二,這樣三階段提交就有CanCommit、PreCommit、DoCommit三個階段。
階段一:CanCommit階段
3PC的CanCommit階段其實和2PC的準備階段很像。協調者向參與者發送commit請求,參與者如果可以提交就返回Yes響應,否則返回No響應。
- 事務詢問 協調者向參與者發送CanCommit請求。詢問是否可以執行事務提交操作。然后開始等待參與者的響應。
- 響應反饋 參與者接到CanCommit請求之后,正常情況下,如果其自身認為可以順利執行事務,則返回Yes響應,并進入預備狀態。否則反饋No
階段二:PreCommit階段
協調者根據參與者的反應情況來決定是否可以記性事務的PreCommit操作。根據響應情況,有以下兩種可能:
假如協調者從所有的參與者獲得的反饋都是Yes響應,那么就會執行事務的預執行。
- 發送預提交請求 協調者向參與者發送PreCommit請求,并進入Prepared階段。
- 事務預提交 參與者接收到PreCommit請求后,會執行事務操作,并將undo和redo信息記錄到事務日志中。
- 響應反饋 如果參與者成功的執行了事務操作,則返回ACK響應,同時開始等待最終指令。
假如有任何一個參與者向協調者發送了No響應,或者等待超時之后,協調者都沒有接到參與者的響應,那么就執行事務的中斷。
- 發送中斷請求 協調者向所有參與者發送abort請求。
- 中斷事務 參與者收到來自協調者的abort請求之后(或超時之后,仍未收到協調者的請求),執行事務的中斷。
階段三:doCommit階段
該階段進行真正的事務提交,也可以分為以下兩種情況。
執行提交
- 發送提交請求 協調接收到參與者發送的ACK響應,那么他將從預提交狀態進入到提交狀態。并向所有參與者發送doCommit請求。
- 事務提交 參與者接收到doCommit請求之后,執行正式的事務提交。并在完成事務提交之后釋放所有事務資源。
- 響應反饋 事務提交完之后,向協調者發送Ack響應。
- 完成事務 協調者接收到所有參與者的ack響應之后,完成事務。
中斷事務
協調者沒有接收到參與者發送的ACK響應(可能是接受者發送的不是ACK響應,也可能響應超時),那么就會執行中斷事務。
- 發送中斷請求 協調者向所有參與者發送abort請求
- 事務回滾 參與者接收到abort請求之后,利用其在階段二記錄的undo信息來執行事務的回滾操作,并在完成回滾之后釋放所有的事務資源。
- 反饋結果 參與者完成事務回滾之后,向協調者發送ACK消息
- 中斷事務 協調者接收到參與者反饋的ACK消息之后,執行事務的中斷。
在doCommit階段,如果參與者無法及時接收到來自協調者的doCommit或者rebort請求時,會在等待超時之后,會繼續進行事務的提交。(其實這個應該是基于概率來決定的,當進入第三階段時,說明參與者在第二階段已經收到了PreCommit請求,那么協調者產生PreCommit請求的前提條件是他在第二階段開始之前,收到所有參與者的CanCommit響應都是Yes。(一旦參與者收到了PreCommit,意味他知道大家其實都同意修改了)所以,一句話概括就是,當進入第三階段時,由于網絡超時等原因,雖然參與者沒有收到commit或者abort響應,但是他有理由相信:成功提交的幾率很大。
3PC優缺點
相比較于2PC協議,三階段提交最大的優點就是降低了參與者的阻塞范圍,并且能后在出現單點故障后繼續達成一致,但是也引入了新的問題,例如在參與者接收到preCommit消息后,如果出現網絡分區,此時協調者所在的節點和參與者無法進行正常的網絡通信,在這種情況下,該參與者依然會進行事務的提交,最終造成數據的不一致問題。
關于PAXOS協議,感覺還是理解的不太透測,后續的文章在介紹吧。