為什麼PBFT需要3個階段訊息?

2021-10-03 22:15:02 字數 3622 閱讀 1562

在面試的時候,很多同學的簡歷熟悉pbft共識演算法,在現場面試的時候,卻只能說個主要邏輯,離完整的演算法,還差十萬八千里,相似從網路上看了一些文章,就算是熟悉了。當我問「為什麼pbft需要3個階段訊息?2個階段行不行」時,還沒有人能回答出來。

萊斯利·蘭波特在其**[1]中描述了如下拜占庭問題:

一組拜占庭帝國的將軍分別各率領一支軍隊共同圍困一座城市。為了簡化問題,將各支軍隊的行動策略限定為進攻或撤離兩種。因為部分軍隊進攻,或部分軍隊撤離可能會造成災難性後果,因此各位將軍必須通過投票來達成一致策略,即所有軍隊一起進攻或所有軍隊一起撤離。因為各位將軍分處城市不同方向,他們只能通過信使互相聯絡。在投票過程中,每位將軍都將自己投票進攻還是撤退的資訊,通過信使分別通知其他所有將軍,這樣一來每位將軍根據自己的投票,和其他所有將軍送來的資訊,就可以知道共同的投票結果,而決定行動策略。

問題在於,將軍中可能出現叛徒(壞將軍),他們不僅可能向較為糟糕的策略投票,還可能選擇性地傳送投票資訊。阻止好將軍達成一致的形成策略。

摘自:維基百科:拜占庭將軍問題,有刪改。

很多人喜歡玩狼人殺,我也喜歡,但我玩的很菜,我用狼人殺跟拜占庭將軍問題做個模擬。

在狼人殺開局的時候,你是好人,並且不知道自己的隊友是誰,也不知道狼人是誰,但所有的好人都有乙個共同的目的:乾死狼人,好人獲勝。所以遊戲中需要使用技巧和策略,達成目的。

拜占庭將軍問題是類似的,好的將軍不知道其他將軍是好的,還是壞的,但所有好的將軍的目的是:行動一致,共同進退。所以,它們也需要策略達成一致。

bft是一類解決拜占庭將軍問題的策略/演算法:讓非拜占庭節點達成一致的演算法。在這類**中,拜占庭節點指「壞」的將軍,非拜占庭節點指「好」的將軍。

pbft是實用拜占庭演算法(practical byzantine fault tolerance)的縮寫,該**與2023年發表,另外2023年又發表了一篇practical byzantine fault tolerance and proactive recovery,讓pbft擁有恢復能力。

pbft作為解決拜占庭問題的策略:非拜占庭節點不知道哪些是拜占庭節點,哪些是非拜占庭節點,pbft要讓非拜占庭節點達成一致

拜占庭問題是在分布式對等網路,對通訊容錯所提出來的。在真實世界中,拜占庭問題是什麼樣的?

通常使用拜占庭行為,描述拜占庭節點可能的行為,拜占庭行為有:

[外鏈轉存失敗,源站可能有防盜煉機制,建議將儲存下來直接上傳(img-qmyy4rn7-1584263615373)(

3階段訊息是:pre-prepare、prepare和commit。每個訊息都會包含數字簽名,證明訊息的傳送者,以及訊息型別,下文中會省略。

pre-prepare訊息由主節點發出,包含:

務必記牢,m、v、n、d,後面會使用縮寫

prepare是副本節點收到pre-prepare訊息後,做出的響應,傳送給所有副本節點,包含:

prepared狀態:副本i有pre-prepare訊息,且收到2f個有效的prepare訊息。

副本i達到prepared狀態,可以傳送commit訊息,commit訊息的內容和prepare訊息內容相同,但訊息型別和數字簽名是不同的,所以可以區分。

m可以使用d代替,所以prepare和commit訊息使用d代替m,來節省通訊量。

前面提到,pbft解決的是拜占庭問題的一致性,即讓非拜占庭節點達成一致。更具體的說:讓請求m,在view內使用序號n,並且完成執行m,向客戶端傳送響應

這個問題的等價問題是:為什麼pre-prepare和prepare訊息,不能讓非拜占庭節點達成一致?

pre-prepare訊息的目的是,主節點為請求m,分配了檢視v和序號n,讓至少f+1個非拜占庭節點對這個分配組合達成一致,並且不存在,即不存在有2個訊息使用同乙個v和n的情況。

prepared狀態可以證明非拜占庭節點在只有請求m使用上達成一致。主節點本身是認可的,所以副本只需要收集2f個prepare訊息,而不是2f+1個prepare訊息,就可以計算出至少f個副本節點是非拜占庭節點,它們認可m使用,並且沒有另外1個訊息可以使用

既然1個只能對應1個請求m了,達到prepared狀態後,副本i執行請求m,不就達成一致了麼?

並不能。prepared是乙個區域性視角,不是全域性一致,即副本i看到了非拜占庭節點認可了,但整個系統包含3f+1個節點,非同步的系統中,存在丟包、延時、拜占庭節點故意向部分節點傳送prepare等拜占庭行文,副本i無法確定,其他副本也達到prepared狀態。如果少於f個副本成為prepared狀態,然後執行了請求m,系統就出現了不一致。

所以,前2個階段的訊息,並不能讓非拜占庭節點達成一致。

如果你了解2pc或者paxos,我相信可以更容易理解上面的描述。2pc或paxos,第一步只是用來鎖定資源,第2步才是真正去do action。把pre-prepare和prepare理解為第一步,資源是,只有第一步是達不成一致性的。

pbft的**提到了2個不變性,這2個不變性,用來證明pbft如何讓非拜占庭節點達成一致性

第1個不變性,它是由pre-prepare和prepare訊息所共同確保的不變性:非拜占庭節點在同乙個view內對請求的序號達成共識。關於這個不變性,已經在為什麼不能只有前2個階段訊息中論述過。

介紹第2個不變性之前,需要介紹2個定義。

[外鏈轉存失敗,源站可能有防盜煉機制,建議將儲存下來直接上傳(img-ppuxdv7l-1584263615375)(

第2個不變性,如果副本i是committed-local,那麼一定存在committed。

2f+1個commit訊息,去掉最多f個拜占庭節點偽造的訊息,得出至少f+1個非拜占庭節點傳送了commit訊息,即至少f+1個非拜占庭節點是prepared狀態。所以第2個不變性成立。

committed意味著有f+1個非拜占庭節點可以執行請求,而committed-local意味著,副本i看到了有f+1個非拜占庭節點可以執行請求,f+1個非拜占庭節點執行請求,也就達成了,讓非拜占庭節點一致。

雖然我前面使用了2pc和paxos做模擬,但不意味著pbft的commit階段就相當於,2pc和paxos的第2步。因為2pc和paxos處理的cft場景,不存在拜占庭節點,它們的主節點充當了統計功能,統計有多少節點完成了第一步。pbft中節點是存在拜占庭節點的,主節點並不是可靠(信)的,不能依賴主節點統計是否有f+1個非拜占庭節點達成了prepared,而是每個節點各自統計,committed-local讓節點看到了,系統一定可以達成一致,才去執行請求。

本文介紹了2個階段訊息是無法達成一致的原因,而為什麼3階段訊息可以。最核心的還是要理解好,pbft解決了什麼問題,以及它是如何解決的。

pbft解決的是在拜占庭環境下,如何提供一致性,以及如何持續的提供一致性的問題。本文只介紹了如何提供一致性,沒有提如何持續提供一致性,即pbft的可用性。現在,不妨思考一下,view change是如何保證切換時一致性的,是否也需要2個不變性的支援呢?

為什麼PBFT中需要2f 1

關於pbft中為什麼需要2f 1個prepare commit的問題,網上其實有很多部落格和文獻來闡述,如這篇部落格pbft中的幾個重要引數以及這本書 introduction to reliable and secure distributed programming 這些部落格和文獻大都採用了比...

01 為什麼需要訊息佇列?

對於對於這 5 個步驟來說,能否決定秒殺成功,實際上只有風險控制和庫存鎖定這 2 個步驟。只要使用者的秒殺請求通過風險控制,並在服務端完成庫存鎖定,就可以給使用者返回秒殺結果了,對於後續的生成訂單 簡訊通知和更新統計資料等步驟,並不一定要在秒殺請求中處理完成。令牌發生器按照預估的處理能力,勻速生產令...

訊息佇列 01 為什麼需要訊息佇列)

主要功能就是收發訊息,但不僅僅是解決應用之間的通訊問題eg.秒殺系統 流程 風險控制 庫存鎖定 生成訂單 簡訊通知 更新統計資料 使用訊息佇列伺服器只需要先實現風控和庫存鎖定 好處 更快返回結果 減少等待,提公升系統功能 健壯框架設計思路 使用訊息佇列隔離閘道器和後端服務,以達到流量控制和保護後端服...