4.4 PBFT演算法

xiaohuanglv發表於2018-08-25

1999年Castro和Liskov提出的PBFT(Practical Byzantine Fault Tolerance)是第一個得到廣泛應用的BFT演算法。在PBFT演算法中,至多可以容忍不超過系統全部節點數量的1/3的拜占庭節點“背叛”,即如果有 超過2/3的節點正常,整個系統就可以正常工作。早期的拜占庭容錯演算法或者基於同步系統的假設,或者由於效能太低而不能在實際系統中運作。PBFT演算法解 決了原始拜占庭容錯演算法效率不高的問題,將演算法複雜度由指數級降低到多項式級,使得拜占庭容錯演算法在實際系統應用中變得可行。也許就是出於效率的考慮,央 行推出的區塊鏈數字票據交易平臺用的就是優化後的PBFT演算法。騰訊的區塊鏈用的也是PBFT。

在PBFT演算法中,每個副本有3個狀態:pre-prepare、prepared和commited。訊息也有 3種:pre-prepare、prepare和committed。收到pre-prepare訊息並且接受就進入prepared狀態。收到 commit訊息並且接受就進入Committed狀態。下面以一個有4個節點/拷貝的例子說明,這個網路內,僅允許1個拜占庭節點(此處設f=1)。

百花村小學舉行百米賽跑比賽,3年級第一組的選手只有4個人:Alice、Bob、Cathy和David(簡稱 A、B、C、D)。為了節省錢,比賽並沒有請裁判,而是在4個選手中隨機挑出一個做裁判,假設是Alice。眾所周知,百米跑的口令是:“各就各位,預 備,跑!”

這裡“各就各位”就是pre-prepare訊息,選手接受了命令就會腳踩進助跑器,而這一動作被其他選手看到, 就會認為該選手進入了prepared狀態。相當於發了一個prepare訊息給其他選手。同理,預備就是prepare訊息,選手接受了就是雙手撐起, 身子呈弓形,而這一動作被其他選手看到,就會認為該選手進入了committed狀態。

1)假設A是公正的。Alice得到老師示意,3年級第一組準備比賽。Alice就喊:“各就各位!”

老師的示意相當於一個外部訊息請求。Alice收到這個訊息,給訊息編一個號,比如編為030101號。必須編 號,因為比賽有一個規則(假想),連續4次起跑失敗,整個組都被淘汰。B、C、D同學收到口令後,如果認為命令無誤,便都把腳踩進助跑器(拜占庭的那個人 例外)。而這一個動作又相當於互相廣播了一個prepare訊息。A、B、C、D選手互相看到對方的動作,如果確認多於f個人(由於此處f=1,所以至少 是2個人)的狀態和自己應有的狀態相同,則認為大家進入prepared狀態。選手會將自己收到的pre-prepare和傳送的prepare資訊記錄 下來。

2)假設A是公正的。Alice看到至少2個人進入prepare狀態,Alice就接著喊:“預備,跑!”。

3)接下來發生的事類似上一步:B、C、D同學收到口令後(相當於收到commit訊息),如果認為命令無誤,便 都雙手撐起,身子呈弓形(拜占庭的那個人例外)。而這一個動作又相當於互相廣播了一個commit訊息。A、B、C、D選手互相看到對方的動作,如果確認 多於f個人(由於此處f=1,所以至少是2個人)的狀態和自己應有的狀態相同,則認為大家進入committed狀態。當大家都確認進入 Committed狀態後,就可以起跑了!

4)假設A是不公正的。A就會被換掉,重新選一個選手B發令。

這時候,由於所有選手都記錄了自己的狀態和接受/傳送的資訊。那些換掉前已經是Committed狀態的選手,開 始廣播commit訊息,如果確認多於f個人(由於此處f=1,所以至少是2個人)的狀態和自己應有的狀態相同,則認為大家進入committed狀態。 而對於換掉前是prepared和pre-prepare狀態的選手,則完全作廢以前的命令和狀態,重新開始。

PBFT演算法的主要優點如下。

·PBFT演算法共識各節點由業務的參與方或者監管方組成,安全性與穩定性由業務相關方保證。

·共識的時延大約在2~5秒,基本達到商用實時處理的要求。

·共識效率高,可滿足高頻交易量的需求。

因為非常適合聯盟鏈的應用場景,PBFT及其改進演算法因此成為目前使用最多的聯盟鏈共識演算法。改進主要集中在:①修改底層網路拓撲的要求,使用P2P網路;②可以動態地調整節點數量;③減少協議使用的訊息數量等。

不過PBFT仍然是依靠法定多數(quorum),一個節點一票,少數服從多數的方式,實現了拜占庭容錯。對於聯盟鏈而言,這個前提沒問題,甚至是優點所在。但是在公有鏈中,就有很大的問題。

來源:我是碼農,轉載請保留出處和連結!

本文連結:http://www.54manong.com/?id=95

'); (window.slotbydup = window.slotbydup || []).push({ id: "u3646208", container: s }); })();
'); (window.slotbydup = window.slotbydup || []).push({ id: "u3646147", container: s }); })();

相關文章