分佈式一致性——二階段提交協議,三階段提交協議

分佈式系統,這早已不是什麼新鮮的東西了,在分佈式系統的架構設計過程中,往往會存在分佈式一致性的問題,經過前人的辛苦探究,提出了二階段提交協議,三階段提交協議,Paxos算法等等,用來解決分佈式一致性的問題。今天我就講一下,二階段提交協議和三階段提交協議的過程,以及它們的優缺點。

2PC,就是二階段提交協議。顧名思義,就是將事務的提交過程分成兩個階段來處理。那我們來看看這兩個階段分別做了什麼。

階段一:

   1.提交事務請求:

      協調者向所有的參與者發送事務內容,詢問是否可以執行事務提交操作,並開始等待各參與者的響應。

   2.執行事務:

      各個參與者節點執行事務操作。並將Undo和Redo信息記入事務日誌中。

   3.各參與者向協調者反饋事務詢問的響應:

      如果參與者成功執行了事務操作,那麼就反饋給協調者Yes響應,表示事務可以執行;如果參與者沒有成功執行事務,那麼就反饋給協調者No響應,表示事務不可以執行。

階段二:

   1.執行事務提交:

      假如協調者從所有參與者獲得的響應都爲Yes,那麼就執行事務提交,協調者向所有參與者節點發出Commit請求。

   2.參與者提交事務:  

      參與者接收到Commit請求後,會正式執行事務提交操作,並在完成提交之後釋放在整個事務執行期間佔用的事務資源,並向協調者發送Ack消息。

   3.完成事務:

      協調者接收到所有參與者反饋的Ack消息後,完成事務。

這裏我畫了一張時序圖,來說明其中的過程,如圖所示:

中斷事務

假如任何一個參與者反饋給協調者No響應,或者在等待超時之後,協調者沒有收到所有參與者的響應,那麼就會中斷事務。

   1.發送回滾請求

      協調者向所有參與者發送Rollback請求。

   2.事務回滾

     參與者接收到Rollback請求後,會利用其在階段一中記錄的Undo信息來執行事務回滾操作,完成回滾之後釋放在整個事務執行期間佔用的資源,並向協調者發送Ack消息,協調者接收到所有的參與者反饋的Ack消息後,完成事務中斷。

中斷的過程就是這樣,下面一張時序圖,描述中斷事務的過程。

二階段提交協議的整個過程就是這樣,這種先請求後提交的方式,能夠保證所有節點在進行事務處理過程中保持原子性,進行統一的提交或回滾,可以看作是一個強一致性的算法。那我們就來思考一下,它有哪些優點,以及會帶來什麼問題。

優點:簡單好用,實現方便。

缺點:同步阻塞,單點問題,還是會有數據不一致的情況出現。

同步阻塞:在二階段提交事務的過程中,所有參與該事務操作的邏輯都處於阻塞狀態,各個參與者在等待其他參與者的響應過程中,無法做其他的操作。

單點問題:在二階段提交協議中,協調者這個角色是很重要的,一旦協調者掛掉,將導致整個提交流程無法運轉,若是在第二階段協調者掛掉,參與者將一直處於鎖定事務資源的狀態,無法繼續完成事務操作。

數據不一致:若是在第二階段,協調者在向所有參與者發送commit請求時,由於局部網絡的故障,只有部分參與者受到commit請求,提交事務,這樣沒有受到commit請求的就沒有提交事務,出現了數據不一致的情況。

3PC,就是三階段提交協議,顧名思義,就是把事務的提交過程分爲三個階段,實際上它就是在原來二階段提交上做了一部分改進,那我們就來看看它的過程,以及它到底改進了什麼。

階段一:CanCommit

     事務詢問:

     協調者向所有的參與者發送一個包含事務內容的canCommit請求,詢問是否可以執行事務提交操作,並開始等待各個參與者的響應。參與者接收請求後,正常情況下,如果認爲其自身可以順利執行事務,那麼會反饋Yes響應,並進入預備狀態,否則反饋No響應。

階段二:PreCommit

在階段二,協調者根據各參與者的反饋情況來決定是否可以進行事務的PreCommit操作,正常情況下,包含兩種可能。一種是參與者全部反饋Yes響應,則進入預提交階段,另一種時有參與者反饋No響應或者等待超時後,沒有收到全部的反饋響應,則會中斷事務,我們來分別看一下這兩種情況。

第一種:預提交:

   協調者向所有的參與者發送PreCommit請求,並進入Prepared階段。

   參與者接收到preCommit的請求,執行事務操作,並將Undo和Redo信息記錄到事務日誌中,然後向協調者反饋Ack響應,等待最終的指令提交或中止。

第二種:中斷事務:

   協調者向所有的參與者發出abort請求,參與者無論是收到協調者的abort請求,還是等待請求過程中超時,參與者都會中斷事務。

階段三:doCommit

這一階段,即將開始真正的事務提交,同樣也會存在兩種可能的情況。

第一種:執行提交:

   1.發送提交請求:

      進入這一階段:假如協調者處於正常的工作狀態,並且它接收到了來自所有參與者的Ack響應,那麼它將從預提交狀態轉換到提交狀態,並向所有的參與者發送doCommit請求。

   2.事務提交:

     參與者接收到doCommit請求後,會正式執行事務提交操作,並在完成提交之後釋放在整個事務執行期間佔用的事務資源,並向協調者發送Ack消息。協調者接收到所有參與者反饋的Ack消息後,完成事務。

第二種:中斷事務:

   進入這一階段,假設協調者處於正常狀態(這個很關鍵),並且有任意一個參與者向協調者反饋了No響應,或者等待超時之後,協調者無法接收到所有參與者的反饋響應。那麼就會中斷事務。

   協調者向所有參與者節點發送abort請求。

   各個參與者接收到abort請求後,會利用其在階段二中記錄的Undo信息來執行事務回滾操作,並在完成回滾之後釋放在整個事務執行期間佔用的資源,並向參與者發送Ack消息。協調者接收到所有參與者反饋的Ack消息後,中斷事務。

一旦進入到階段三,可能會存在兩種故障:1.協調者出現問題;2.協調者和參與者之間的網絡出現故障。

無論出現哪種情況,最終都會導致參與者無法及時接收到來自協調者doCommit或是abort請求,針對這樣的異常情況,參與者都會在等待超時之後,繼續提交事務操作。

到這裏三階段提交協議就講完了,相比較於二階段提交協議,它降低了參與者的阻塞範圍,並在出現單點故障後,繼續達成一致。同樣三階段提交協議也會帶來數據不一致的問題,在第二階段,協調者向所有參與者發送preCommit請求時,如果這時網絡出現問題,協調者無法和參與者進行正常通信,參與者此時仍然會提交事務,而協調者等待超時後,進行事務中斷,這樣就會帶來數據不一致的情況。

總結:二階段提交協議和三階段提交協議都是解決分佈式數據一致性問題的優秀算法,儘管從根本上並不能保證絕對的一致性,但也並不影響它們在實際工程上的使用。有句話是這麼說的,在存在消息丟失的不可靠信道上試圖通過消息傳遞的方式達到一致性是不可能的,有興趣的朋友可以研究一下paxos算法以及它的證明過程。

原文:https://blog.csdn.net/rz_0212/article/details/81449657 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章