1. 程式人生 > >【我的區塊鏈之路】- 談一談拜占庭問題的解及PBFT(拜占庭容錯)

【我的區塊鏈之路】- 談一談拜占庭問題的解及PBFT(拜占庭容錯)

首先,我們來說一說什麼是拜占庭問題。

【問題由來】

拜占庭的n個將軍圍攻敵人,n個將軍包圍著敵人,忠誠的將軍希望通過某種協議達成某個命令的一致(比如約定某個時間一起進攻)。但其中一些背叛的將軍會通過傳送錯誤的訊息阻撓忠誠的將軍達成命令上的一致。如果同時發起進攻的將軍數量少於m個,那麼不足以殲滅敵人,反而容易被敵人全部殲滅。怎樣做才能保證有多於m個將軍在同一時間一起發起進攻
 

【注意】:拜占庭問題是建立在通訊通道可信的基礎上的(即: 傳輸過程中,資料不會被竊取的情況下)

【問題實質】:

一群將軍想要實現某一個目標(一致進攻或者一致撤退),但是單獨行動或少於某個數目行動是行不通,必須合作, 達成共識;由於叛徒的存在,將軍們不知道應該如何達到一致。這裡“一致性”才是拜占庭將軍問題探討的內容

“拜占庭將軍問題”模型中,對於將軍們(節點)有兩個預設的假設:
1、 所有忠誠的將軍收到相同的命令後,執行這條命令得到的結果一定是相同的;
2、 如果命令是正確的,那麼所有忠誠的將軍必須執行這條命令。
 

【提出假設】:

我們考慮4個將軍的情況【為什麼是4個而不是5個之類的,後面我們會講】,同時假設4個將軍中最多隻有1個背叛者。當4個將軍A、B、C、D把敵人包圍了之後,必須協商一個統一的時間去發起進攻。

假設A為忠誠的:A將軍派出了3個傳令兵,分別告訴B、C、D將軍,下午1點準時發起進攻。到了下午1點,A、C、D三個將軍發起了進攻,殲滅了敵人,同時他們三個發現B是背叛的。雖然B背叛了,但是對最終任務沒有影響。

假設A是背叛的:會發生什麼情況?A派出3個傳令兵,分別告訴B、C、D將軍在下午1點、2點、3點發起進攻。於是,到了下午1點,B將軍去攻擊敵人,由於寡不敵眾,全軍覆沒;2點,C將軍全軍覆沒;3點,D將軍全軍覆沒。

所以會有兩種情況,

【一】:訊息的發起者是忠誠的

【二】:訊息的發起者是背叛者
 

問題解決的核心是,每一個將軍接收到訊息後都需要對訊息的真實性做判斷,如何做?(用共識演算法做,怎麼做?下面慢慢來說。。。)

當A為叛徒時,可能會導致兩種結果: 【B、C、D 都會在接收到A的訊息後,相互訪問A給其他人的答案。】

(當A只對其中一個說了真話,其他人說了不一樣的假話,則全部節點都不進攻)

(當A只對其中一個人說了假話,則忠誠節點們都會自己通過相互訪問A的訊息來決定進攻時機)

如果,傳送者A和其他2個節點是忠誠的,而B是背叛者時:

(通過相互訪問C、D節點可以自行判斷出正確的答案,從而正確的和A一起發起進攻)

【解決拜占庭問題的演算法】:PBFT (拜占庭容錯演算法)

PBFT演算法的核心理論是:n>=3f+1;n 是系統中的總節點數,f 是允許出現故障的節點數。換句話說,如果這個系統允許出現f個故障,那麼這個系統必須包括n個節點,才能解決故障。

那麼為什麼這麼說呢?

理論的推導過程:

假設總數N個節點, f個故障節點,那麼必須接收到N-f個訊息應答(即 沒有故障的節點的全部應答),就能夠判斷出結果(因為故障節點可能不傳送應答)。N-f個應答中有f個可能是假的(故障節點發出的)【其中這句話最為奇妙,但是確實一個假設,因為可能有網路延遲等等,我們可以認為,作假的節點和真正故障的節點的數目是相等的,這句話值得慢慢體會,為什麼作假節點被認為是f而不是 2f、3f等等,因為我們需要把有問題的節點的容忍度最大化 (系統需要穩定,肯定需要對有問題的節點做最大容忍),即就是  故障節點數目 == 作假節點數目,無論真實數目那邊大,我們f 就是取了最大的那邊的數值】,所以真實的是N-f-f,且 少數服從多數,及剩餘的真實的應答大於有問題的應答, 即N-f-f > f ==> N > 3f。

所以:  N_min = 3f + 1
 

當然下面我們也可以藉助推理來一步步推匯出來: 

假設 n 為系統總節點數,m 為作假/故障節點數

1) m = 1,n = 3 的情形: n=3,意味著一個司令傳送命令給兩個副官,m=1意味著他們中有一個叛徒。 首先考慮司令忠誠而副官2是叛徒的情況。

(m=1,n=3中司令忠誠而副官2是叛徒的情形)

司令把進攻命令傳給了兩個副官1和副官2,但是由於副官2為了不讓他們達成一致,將司令的命令改成了撤退。那對於副官1來說,他應該如何判斷?L1 無法知道是司令是叛徒還是副官2是叛徒,從而無法判斷

如果,司令為叛徒:

( m=1,n=3中司令是是叛徒的情形)

如果司令是叛徒,兩個副官忠誠,司令會發送兩個不同的命令。當兩個副官對照命令時,他們又凌亂了,無法判斷司令是叛徒或者對方是叛徒,從而又無法判斷。

【結論】:總節點只有3個時,是無法動態容錯的。

(2)m =1,n =4的情形: n=4,意味著一個司令傳送命令給三個副官,m=1意味著他們中有一個叛徒。 首先考慮司令忠誠而副官3是叛徒的情況。

(m=1,n=4中司令忠誠而副官3是叛徒的情形)

倘若司令給各副官傳送的訊息都是進攻(A);之後,叛徒副官3給副官1和副官2說他收到的訊息是撤退(R)。那麼對於副官1(或副官2)來說,他綜合司令、副官3和副官2(或副官1)後得到的訊息向量都將會是(A,A,R),最終會採用 A

如果,司令為叛徒:

假設叛徒司令會給三個副官傳送的資訊是(x,y,z)。之後,三位忠誠的副官將會交換他們收到的資訊。對於副官1,他綜合司令、副官2和副官3後得到的訊息向量將會是(x,y,z),可以發現對於其他兩個忠實的副官,他們得到的訊息向量也將是(x,y,z)。不管x,y,z如何變化,但對於三人來說都是一樣的,所以三個副官將會採用一致的行動,即:本次指令全部作廢。

【結論】:n >= 3m + 1是可以容錯的

PBFT(拜占庭容錯)

基於拜占庭將軍問題,一致性的確保主要分為這三個階段:預準備(pre-prepare)、準備(prepare)和確認(commit)。流程如下圖所示:

其中C為傳送請求端,0、1、2、3為服務端,3為宕機的服務端,具體步驟如下:

1. Request:請求端C傳送請求到任意一節點,這裡是 0

2. Pre-Prepare:服務端0 收到C的請求後進行廣播,擴散至1、2、3

3. Prepare:1、2、3收到後記錄並再次廣播,1 -> 0、2、32 -> 0、1、3,3因為宕機無法廣播

4. Commit:0、1、2、3節點在Prepare階段,若收到超過一定數量的相同請求,則進入Commit階段廣播Commit請求

5.Reply (答覆):0、1、2、3節點在Commit階段,若收到超過一定數量的相同請求,則對C進行答覆

6. 客戶端等待來自不同節點的響應,若有 m+1 個相同的響應結果,則為本次運算的結果

根據上述流程,在 N ≥ 3F + 1 的情況下一致性是可能解決,N為總計算機數,F為有問題的計算機總數

N=4 F=0 時:

得到資料 最終資料
A 1 1 1 1 1
B 1 1 1 1 1
C 1 1 1 1 1
D 1 1 1 1 1

N=4 F=1 時:

得到資料 最終資料
A 1 1 1 0 1
B 1 1 0 1 1
C 1 0 1 1 1
D 0 1 1 1 1

N=4 F=2 時:

得到資料 最終資料
A 1 1 0 0 NA
B 1 0 0 1 NA
C 0 0 1 1 NA
D 0 1 1 0 NA

由此可以看出,拜占庭容錯能夠容納將近1/3的錯誤節點誤差

到此,我們的拜占庭問題,及拜占庭容錯演算法就講解完畢了。。