1. 程式人生 > >【讀書筆記-從Paxos到ZooKeeper分散式一致性原理與實踐】第二章 一致性協議

【讀書筆記-從Paxos到ZooKeeper分散式一致性原理與實踐】第二章 一致性協議

2PC與 3PC

在分散式系統中,每個節點都明確知道自己事務操作的成功或失敗,但無法獲取其他分散式節點的操作結果。因此當一個事務需要跨節點進行事務操作時,需要引入協調者(Coordinator)元件來統一排程所有分散式節點的執行邏輯,這些被排程的節點稱為參與者(Participant)。
協調者負責排程參與者的行為,最終決定這些參與者是否提交事務。基於這個思想衍生出二階段提交和三階段提交兩種協議。

2PC

2PC, Two-Phase Commit 的縮寫,即二階段提交。

協議說明

二階段提交協議是將事務提交過程分成了兩個階段來進行處理,執行流程如下:
階段一:提交事務請求
1.事務詢問。協調者向所有的參與者傳送事務內容,詢問是否可以執行事務提交操作,並開始等待各參與者的相應。
2. 執行事務 。各參與節點執行事務操作,並將Undo和Redo資訊記入事務日誌中。
3. 各參與者向協調者反饋事務詢問的相應。 如果參與者執行了事務操作,則反饋給協調者yes相應,表示事務可以執行。如果沒有成功執行,則犯規給No。

由於上面的內容相當於協調者組織參與者的投票,所以二階段提交協議的第一階段也被稱為投票階段。
階段二:執行事務提交
在階段二中,協調者根據參與者反饋情況來決定最終是否可以進行事務提交操作。包含兩種情況:
1.執行事務提交。 如果所有的參與者都反饋YES,則執行事務提交。 協調者向所有參與者傳送事務提交》參與者提交事務》參與者反饋事務提交結果》協調者收到所有參與者的反饋訊息,完成事務提交。
2. 中斷事務。 加入存在參與者相應為NO或者超時,那麼需要中斷事務。 傳送回滾請求》事務回滾》反饋事務回滾結果》中斷事務。

優缺點

優點:原理簡單,實現方便
缺點:同步阻塞,單點問題

3PC

3PC,Three-Phase Commit,三階段提交協議,由CanCommit、PreCommit、Do Commit三階段組成。

階段一:Can Commit

  1. 事務詢問。協調者向參與者傳送一個包含事務內容的canCommit請求,詢問是否可以執行事務提交操作,並開始等待參與者相應。
  2. 個參與者向協調者反饋事務詢問的相應。

階段二:PreCommit

執行事務PreCommit

假如協調者獲取的所有相應都是YES則執行事務預提交。
1.傳送預提交請求。
2.事務預提交
3.各參與中向協調者反饋事務執行結果的相應。

中斷事務

假如協調者獲取的相應存在NO,或者等待超時,則中斷事務。
1. 傳送中斷請求
2. 中斷事務

階段三:DOCommit

真正的事務提交,存在兩種結果:

執行提交

1.傳送提交請求 協調者由預提交轉換到提交狀態,向所有參與者傳送doCommit請求
2.事務提交 參與者收到doCommit請求後,執行事務提交
3. 反饋事務提交結果 參與者完成事務提交後,向協調者傳送ACK訊息
4. 完成事務 協調者接收到所有參與者反饋的ACK訊息後,完成事務

中斷事務

1,傳送中斷請求
2,事務回滾
3,反饋事務回滾結果
4,中斷事務
進入階段三也存在兩種故障:
1,協調者出現問題
2,協調者和參與者網路出現問題。

Paxos演算法

Paxos演算法詳解

Paxos演算法的核心一致性演算法即 synod演算法。

問題描述

假設一組可以提出提案的程序集合,那麼對於一個一致性演算法來說需要保證以下幾點:
* 在這些被提出的提案中,只有一個會被選定
* 如果沒有提案被提出,那麼就不會有被選定的提案
* 當一個提案被選定後,程序可以獲取被選定的提案資訊

對於一致性來說,安選型需求如下:
* 只有被提出的提案才能被選定
* 只能有一個值被選定
* 如果某個程序認為某個提案被選定了,那麼這個提案必須是真的被選定的那個

在Paxos演算法中,有三個參與角色,Proposer、Acceptor、Learner。在具體的實現中,一個程序不止一種角色。假設不同參與者之間可以通過手法訊息來進行通訊,那麼:
* 每個參與者以任意的速度進行,可能會因為出錯而停止,也可能重啟。同時,及時一個提案被選定後,也可能所有的參與者都會失敗或重啟,因此除非那些失敗或者重啟的參與者都可以記錄某些資訊,否則無法確定最終的值。
* 訊息在傳輸過程中可能會出現不可預知的延遲,也可能重複或丟失,但是訊息不會被損壞,即訊息不會被篡改。

提案的選定

要選定一個唯一提案的最簡單方式就是隻有一個Accpetor存在,Proposer傳送提案給Accpetor, Accpetor選擇第一個提案。但是一旦唯一的Acceptor故障,整體系統會故障。
最好的方案,是適應多個Acceptor避免Acceptor的單點問題。多個Acceptor的選取:Proposer向一個Acceptor集合傳送提案,同樣集合中的每個Acceptor都可能會批准該提案,當有足夠多的Acceptor批准這個提案的時候,我們就認為該提案被選定了。我們假設足夠多的Acceptor是整個Acceptor集合的一個子集,並且讓這個集合大得可以包含Acceptor集合中的大多數成員,因為任意兩個包含大多數Acceptor的子集都至少有一個公共成員。我們再規定,每一個Acceptor最多隻能批准一個天,那麼就能保證只有一個提案被選定了。

推導過程

在沒有訊息丟失和失敗的情況下,我們希望即使在只有一個提案被提出的情況下,仍然可以選出一個天,就暗示如下:
P1:一個Acceptor必須批准它收到的第一個提案。
上面的問題引出一個問題:當多個提案被不同的Proposer同時提出,這可能導致雖然每個Acceptor都批准它收到的第一個提案,但是美譽一個提案是由多數人都批准的。
在P1的基礎上,再加上一個天被選定需要由半數以上的Acceptor批准的需求,按時一個Acceptor必須能夠批准不止一個提案。在這裡我們使用一個全域性編號來唯一標識每一個被Acceptor批准的提案,當一個提案被半數以上的Acceptor批准後,我們就認為該提案被選定。
P2:如果編號為M1、Value為V1的提案被選定了,那麼所有比編號M1更高的,且被選定的提案,其Value值必須是V1。
因為提案的編號是唯一的,條件2保證了只有一個Value(提案具體的內容)被選定這一關鍵屬性。同事一個提案要被選定,首先必須只有一個Acceptor批准,由此我們通過滿足如下條件來滿足P2:
*P2a:如果編號為M0、Value為V0的提案被選定了,那麼所有比編號M0更高,且被批准的提案,其Value必須為V0.
如上,可能存在問題,某個Acceptor未收到任何訊息,提案已經被選定了。需要對P2a進行強化:
* P2b:如果一個提案 M0 V0 被選定後,那麼任何Proposer產生的編號更高的提案,其Value都為V0。

因為一個提案必須被Proposer提出後才能被Acceptor批准,因此P2b包含了P2a,進而包含了P2,所以,P2b成立即可:
假設某個提案M0 V0已經被選定了,證明任何編號Mn > M0的天,其value值都為V0。

數學歸納法證明

我們可以通過對Mn進行第二數學歸納法來進行證明,也就是說需要證明一下結論:
假設編號M0到Mn-1之間的提案,其Value值都是V0,證明編號為Mn的提案的Value值也為V0。
因為編號M0的提案已經被選定了,這就意味肯定存在一個由半數以上的Acceptor組成的集合C,C中的每個Acceptor都批准了改提案。再假設,M0的提案也被選定意味著:
C中的每個Acceptor都批准了一個編號在M0到Mn-1範圍內的提案,並且每個編號在m0到Mn-1範圍內的被Acceptor批准的提案,其Value都為V0。
因為任何包含半數以上的Acceptor的集合S都至少包含C中的一個成員,因此我們可以認為如果保持了下面的P2c的不變形,那麼編號為Mn的天的Value也是V0。
P2c:對於任意的Mn和Vn,如果Mn Vn被提出,那麼肯定存在一個由半數以上的Acceptor組成的集合S,滿足一下兩個條件中的任意一個。
* S中不存在任何批准過編號下小於Mn的提案的Acceptor.
* 選取S中所有的Acceptor批准的編號小於Mn的提案,其中編號最大的那個提案的Value是Vn

Acceptor批准提案

一個Acceptor可能會收到Proposer的兩種請求,分別是Prepare和Accept請求,對這兩個請求做出的相應的條件分別如下:
* Prepare請求:Acceptor可以在任何時候相應一個Prepare請求
* Accept請求:在不違背Accept現有承諾的前提下,可以任意相應Accept請求

因此,對Acceptor邏輯處理的約束條件定義如下;
* P1a:一個Acceptor只要尚未相應任何編號大於Mn的Prepare請求,那麼它就可以接受這個編號為Mn的提案

演算法陳述

綜合之前的內容,結合Proposer和Acceptor對提案的處理,得到如下類似兩階段提交的演算法執行過程:

階段一

  1. Proposer選擇一個提案編號Mn,然後向Acceptor的某個超過半數的子整合員傳送編號為Mn的Prepare請求。
  2. 如果一個Acceptor接收到一個編號為Mn的Prepare請求,且編號Mn大於該Acceptor已經相應的所有Prepare請求的編號,那麼它就會對它已經批准的過的最大編號的提案最為響應反饋給Proposer,同時該Acceptor承諾不會再批准編號小於Mn的提案。

階段二

1,如果Proposer收到來自半數以上的Acceptor對於其發出的編號為Mn的Prepare請求的相應,那麼它就會發出一個針對Mn Vn的提案給Acceptor。
2,如果Acceptor收到這個針對Mn Vn的提案的Acceptor請求,只要該Acceptor尚未對編號大於Mn的Prepare請求做出相應,它就通過這個提案。

提案的獲取

Learner獲取提案分為以下幾個方案:
* Learner獲取一個已經被選定的提案的前提是,該提案已經被半數以上的Acceptor批准,因此,最簡單的做法就是一旦Acceptor批准了一個提案,就將該提案發送給所有的Learner。 優點:快速選定提案 缺點:內個Acceptor與所有的Learner逐個通訊,通訊次數過多。
* 所有的Acceptor將他們對提案的批准都統一發給特定的主Learner,不考慮拜占庭將軍問題前提下,當一個議案被選中後,主Learner負責通知其他Learner。優點:通訊次數較少。缺點:主Learner可能會故障。
* 結合方案二,我們將主Learner作為一個集合來處理,則解決上述兩個問題。

通過選取主Proposer保證演算法的活性

Proposer P1提出了M1提案,完成了階段一,P2同時提出M2提案完成階段一,於是Acceptor不再批准M2的提案。當P1進入第二階段時,會被忽略,於是p1再次進入第一階段,獲取M3 , M3大於M2,由導致P2在第二階段忽略,由此進入死迴圈。
為了解決以上問題,選取一個主Proposer,並規定,只有主Proposer才能提出議案。這樣子,只要主Proposer和過半的Acceptor正常通訊,凡是主Proposer提出一個編號更改的提案,該提案會被批准,當發現有更大的提案時,則丟棄當前的較小提案。