PBFT共識算法詳解

PBFT(Practical Byzantine Fault Tolerance,實用拜占庭容錯)

一.概述

拜占庭將軍問題最先是由 Leslie Lamport 在 1982 年發表的論文《The Byzantine Generals Problem 》提出的, 他證實了在將軍總數大於 3f ,背叛者爲f 或者更少時,忠誠的將軍能夠達成命令上的一致,即 3f+1<=n 。算法複雜度爲 O(nf+1) 。而 Miguel Castro 和 Barbara Liskov 在1999年發表的論文《 Practical Byzantine Fault Tolerance 》中首次提出 PBFT算法,該算法容錯數量也知足 3f+1<=n,也即最大的容錯做惡節點數f=(n-1)/3。算法複雜度爲 O(n2),將系統的複雜度由指數級別下降爲多項式級別,使得拜占庭容錯算法在實際系統應用中變得可行。算法

那麼爲何PBFT算法的容錯數量知足3f+1<=n呢?網絡

由於 PBFT 算法的除了須要支持容錯故障節點以外,還須要支持容錯做惡節點。假設集羣節點數爲 N,有問題的節點爲 f。有問題的節點中,能夠既是故障節點,也能夠是做惡節點,或者只是故障節點或者只是做惡節點。那麼會產生如下兩種極端狀況:異步

  1. 這f 個有問題節點既是故障節點,又是做惡節點,那麼根據少數服從多數的原則,集羣里正常節點只須要比f個節點再多一個節點,即 f+1 個節點,確節點的數量就會比故障節點數量多,那麼集羣就能達成共識,即總節點數爲f+(f+1)=n,也就是說這種狀況支持的最大容錯節點數量是 (n-1)/2。
  2. 故障節點和做惡節點都是不一樣的節點。那麼就會有 f 個做惡節點和 f 個故障節點,當發現節點是做惡節點後,會被集羣排除在外,剩下 f 個故障節點,那麼根據少數服從多數的原則,集羣里正常節點只須要比f個節點再多一個節點,即 f+1 個節點,確節點的數量就會比故障節點數量多,那麼集羣就能達成共識。因此,全部類型的節點數量加起來就是 f+1 個正常節點,f個故障節點和f個做惡節點,即 3f+1=n。

結合上述兩種狀況,所以PBFT算法支持的最大容錯節點數量是(n-1)/3。函數


二.PBFT共識算法流程

角色劃分性能

  • Client:客戶端節點,負責發送交易請求。測試

  • Primary: 主節點,負責將交易打包成區塊和區塊共識,每輪共識過程當中有且僅有一個Primary節點。優化

  • Replica: 副本節點,負責區塊共識,每輪共識過程當中有多個Replica節點,每一個Replica節點的處理過程相似。編碼

其中,Primary和Replica節點都屬於共識節點。加密

算法流程3d

PBFT 算法的基本流程主要有如下四步:

  1. 客戶端發送請求給主節點
  2. 主節點廣播請求給其它節點,節點執行PBFT算法的三階段共識流程
  3. 節點處理完三階段流程後,返回消息給客戶端。
  4. 客戶端收到來自 f+1 個節點的相同消息後,表明共識已經正確完成。

算法的核心三個階段分別是 pre-prepare 階段(預準備階段),prepare 階段(準備階段), commit 階段(提交階段)。圖中的C表明客戶端,0,1,2,3 表明節點的編號,其中0 是主節點primary,打×的3表明多是故障節點或者是做惡節點,這裏表現的行爲就是對其它節點的請求無響應。整個過程大體是以下:

首先,客戶端向主節點0發起請求<<REQUEST,o,t,c>> 其中t是時間戳,o表示操做,c是這個client,主節點收到客戶端請求,會向其它節點發送 pre-prepare 消息,其它節點就收到了pre-prepare 消息,就開始了這個核心三階段共識過程了。

  • Pre-prepare 階段:副本節點replica收到 pre-prepare 消息後,會有兩種選擇,一種是接受,一種是不接受。何時纔不接受主節點發來的 pre-prepare 消息呢?一種典型的狀況就是若是一個replica節點接受到了一條 pre-prepare 消息<<PRE_PREPARE,v,n,d>,m>,其中,v 表明視圖編號(視圖的編號是什麼意思呢?好比當前主節點爲 A,視圖編號爲 1,若是主節點換成 B,那麼視圖編號就爲 2)n表明序號(主節點收到客戶端的每一個請求都以一個編號來標記)d表明消息摘要m表明原始消息數據。消息裏的 v 和 n 在以前收到裏的消息是曾經出現過的,可是 d 和 m 卻和以前的消息不一致,或者請求編號n不在高低水位之間,這時候就會拒絕請求。拒絕的邏輯就是主節點不會發送兩條具備相同的 v 和 n ,但 d 和 m 卻不一樣的消息。

    Replia節點接收到pre-prepare消息,進行如下消息驗證:

    1. 消息m的簽名合法性,而且消息摘要d和消息m相匹配:d=hash(m)
    2. 節點當前處於視圖v中
    3. 節點當前在同一個(view v ,sequence n)上沒有其它pre-prepare消息,即不存在另一個m'和對應的d' ,d'=hash(m')
    4. h<=n<=H,H和h表明序號n的高低水位。
  • Prepare 階段:當前節點贊成請求後會向其它節點發送 prepare 消息 <PREPARE,v,n,d,i>同時將消息記錄到log中,其中i用於表示當前節點的身份。同一時刻不是隻有一個節點在進行這個過程,可能有 n 個節點也在進行這個過程。所以節點是有可能收到其它節點發送的 prepare 消息的,當前節點i驗證這些prepare消息和本身發出的prepare消息的v,n,d三個數據是否都是一致的。驗證經過以後,當前節點i將prepared(m,v,n) 設置爲true,prepared(m,v,n) 表明共識節點認爲在(v,n)中針對消息m的Prepare階段是否已經完成。在必定時間範圍內,若是收到超過 2f 個其餘節點的prepare 消息,就表明 prepare 階段已經完成。最後共識節點i發送commit消息並進入Commit階段。

  • Commit 階段:當前節點i接收到2f個來自其餘共識節點的commit消息<COMMIT,v,n,d,i>同時將該消息插入log中(算上本身的共有2f+1個),驗證這些commit消息和本身發的commit消息的v,n,d三個數據都是一致後,共識節點將committed-local(m,v,n)設置爲true,committed-local(m,v,n)表明共識節點肯定消息m已經在整個系統中獲得至少2f+1個節點的共識,而這保證了至少有f+1個non-faulty節點已經對消息m達成共識。因而節點就會執行請求,寫入數據。

處理完畢後,節點會返回消息<<REPLY,v,t,c,i,r>>給客戶端,當客戶端收集到f+1個消息後,共識完成,這就是PBFT算法的所有流程。


三.垃圾回收

根據前面的算法部分能夠發現,咱們須要不斷地往log中插入消息,在view change時恢復須要用到。因而log很快就會變得很佔內存,這時候須要有一種方式清理掉無用的log。當某一request已經被f+1個正常節點執行完畢後,並當view change能夠向其餘節點證實當前狀態的正確性,與該request相關的message就能夠刪除了。

每執行一個request就產生一次證實效率過於低下,論文中是每處理必定的request後產生一次證實。也就是當request的序號n % C ( 某 一 定 值 ) =0時,產生一個checkpoint,節點i多播消息<<CHECKPOINT,n,d,i>>給其餘節點,當節點接收2f+1個消息時,該checkpoint變爲stable checkpoint,也就是這2f+1個節點能夠證實該狀態的正確性,同時能夠刪除序號≤n的消息相關的log信息和checkpoint信息。

什麼是 checkpoint 呢? checkpoint 就是當前節點處理的最新請求序號。前文已經提到主節點收到請求是會給請求記錄編號的。好比一個節點正在共識的一個請求編號是101,那麼對於這個節點,它的 checkpoint 就是101。

什麼是 stable checkpoint (穩定檢查點)呢?stable checkpoint 就是大部分節點 (2f+1個) 已經共識完成的最大請求序號。好比系統有 4 個節點,三個節點都已經共識完了的請求編號是 213 ,那麼這個 213 就是 stable checkpoint 了,也就能夠刪除213 號以前的記錄了。

什麼是高低水位呢?低水位就是stable checkpoint的序號n,高水位是stable checkpoint的序號n + K,其中K是定值,通常是C(上面說起到的某必定值)的整數倍。


四.視圖更換(view change)

正常狀況下,client將request發給一個主節點primary,而後主節點將request多播到其餘節點replica,進行一個view。然而當主節點出錯或成爲惡意節點時,就須要進行視圖更換(view change),也就是選擇(輪換法)下一個replica節點做爲主節點,視圖編號v進行+1操做,共識過程進入下一個view。

如圖所示, view change 會有三個階段,分別是 view-changeview-change-acknew-view 階段。replica節點認爲主節點primary有問題時,會向其它節點發送 view-change 消息<<VIEW−CHANGE,v+1,n,C,P,i>> 其中:

  • v:上一個視圖編號
  • n:節點i的stable checkpoint的編號
  • C:2f+1個節點的有效checkpoint信息的集合
  • P:節點i中的上一個視圖中編號大於n而且達到prepared狀態的請求消息的集合
  • i:節點的編號

當前存活的節點編號最小的節點將成爲新的主節點。當新的主節點收到 2f 個其它節點的 view-change 消息,則證實有足夠多人的節點認爲主節點有問題,因而就會向其它節點廣播 new-view 消息<<NEW-VIEW,v+1,V,O>>

其中:

  • v:上一個視圖編號

  • V:新的主節點接收到的有效的視圖編號爲v+1的view-change消息集合

  • O:pre-prepare消息的集合。假設 O 集合裏消息的編號範圍:(min~max),則 Min 爲 V 集合最小的 stable checkpoint , Max 爲 V 集合中最大序號的 prepare 消息。最後一步執行 O 集合裏的 pre-preapare 消息,每條消息會有兩種狀況: 若是 max-min>0,則產生消息 <<pre-prepare,v+1,n,d>> ;若是 max-min=0,則產生消息 <<pre-prepare,v+1,n,d(null)>>

注意:replica節點不會發起 new-view 事件。對於主節點,發送 new-view 消息後會繼續執行上個視圖未處理完的請求,從 pre-prepare 階段開始。其它節點驗證 new-view 消息經過後,就會處理主節點發來的 pre-prepare 消息,這時執行的過程就是前面描述的PBFT過程。到這時,正式進入 v+1 (視圖編號加1)的時代了。


五.優缺點

優勢:

  • 通訊複雜度O(n2),解決了原始拜占庭容錯(BFT)算法效率不高的問題,將算法複雜度由指數級下降到多項式級,使得拜占庭容錯算法在實際系統應用中變得可行。
  • 首次提出在異步網絡環境下使用狀態機副本複製協議,該算法能夠工做在異步環境中,而且經過優化在早期算法的基礎上把響應性能提高了一個數量級以上。做者使用這個算法實現了拜占庭容錯的網絡文件系(NFS),性能測試證實了該系統僅比無副本複製的標準NFS慢了3%。
  • 使用了加密技術來防止欺騙攻擊和重播攻擊,以及檢測被破壞的消息。消息包含了公鑰簽名(RSA算法)、消息驗證編碼(MAC)和無碰撞哈希函數生成的消息摘要(message digest)。

缺點:

  • 僅僅適用於permissioned systems (聯盟鏈/私有鏈)。
  • 通訊複雜度太高,可拓展性比較低,通常的系統在達到100左右的節點個數時,性能降低很是快。
  • PBFT在網絡不穩定的狀況下延遲很高。
相關文章
相關標籤/搜索