這篇文章主要為大家展示了“hyperledger fabric中Raft共識(shí)插件的示例分析”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“hyperledger fabric中Raft共識(shí)插件的示例分析”這篇文章吧。
成都創(chuàng)新互聯(lián)公司成立于2013年,我們提供高端成都網(wǎng)站建設(shè)、成都網(wǎng)站制作、網(wǎng)站設(shè)計(jì)、網(wǎng)站定制、全網(wǎng)營(yíng)銷推廣、小程序開發(fā)、微信公眾號(hào)開發(fā)、成都網(wǎng)站推廣服務(wù),提供專業(yè)營(yíng)銷思路、內(nèi)容策劃、視覺設(shè)計(jì)、程序開發(fā)來(lái)完成項(xiàng)目落地,為石牌坊企業(yè)提供源源不斷的流量和訂單咨詢。
共識(shí)算法可以讓機(jī)群協(xié)同工作,并且可以容忍部分成員主機(jī)的故障。通常我們提到主機(jī)的故障會(huì)區(qū)分兩種情況對(duì)待:拜占庭故障和非拜占庭故障。
比特幣是第一個(gè)解決了拜占庭故障的去中心化系統(tǒng),它的方法是使用工作量證明共識(shí)(POW)。在一個(gè)存在拜占庭故障的系統(tǒng)中,不僅會(huì)發(fā)生主機(jī)崩潰的問(wèn)題,而且某些成員可能會(huì)存在惡意行為去影響整個(gè)系統(tǒng)的決策過(guò)程。
如果一個(gè)分布式系統(tǒng)可以處理拜占庭故障,那么它就可以容忍任何類型的錯(cuò)誤發(fā)生。常見的支持拜占庭故障的共識(shí)算法包括PoW、PoS、PBFT和RBFT。
Raft只能處理非拜占庭故障,也就是說(shuō)Raft共識(shí)可以容忍系統(tǒng)崩潰、網(wǎng)絡(luò)中斷/延遲/包丟失等故障。常見的支持非拜占庭故障的共識(shí)算法或系統(tǒng)包括:Raft、Kafka、Paxos和Zookeeper。
那么,Hyperledger Fabric為什么不使用可以容忍拜占庭故障的共識(shí)機(jī)制呢?那樣不是更安全嗎?
一個(gè)原因在于系統(tǒng)的復(fù)雜性與安全性的設(shè)計(jì)折中。假設(shè)一個(gè)系統(tǒng)中可能同時(shí)有n個(gè)節(jié)點(diǎn)發(fā)生拜占庭故障,那么拜占庭容錯(cuò)要求系統(tǒng)至少有3n+1個(gè)節(jié)點(diǎn)存在。例如,為了應(yīng)對(duì)100個(gè)潛在的惡意節(jié)點(diǎn),你至少需要部署301個(gè)節(jié)點(diǎn)。這就讓系統(tǒng)更復(fù)雜。Raft則只需要2n+1個(gè)節(jié)點(diǎn)來(lái)應(yīng)對(duì)潛在的n個(gè)節(jié)點(diǎn)的非拜占庭故障,顯然復(fù)雜性和成本要低一些。因此有些分布式系統(tǒng)還是更傾向于Raft,尤其是考慮到像Hyperledger Fabric這種許可制的聯(lián)盟鏈環(huán)境中,通常會(huì)使用數(shù)字證書等安全機(jī)制來(lái)增強(qiáng)安全性,因此存在惡意節(jié)點(diǎn)的可能性很小。
Raft是一個(gè)分布式崩潰故障容錯(cuò)共識(shí)算法,它可以保證在系統(tǒng)中部分節(jié)點(diǎn)出現(xiàn)非拜占庭故障的情況下,系統(tǒng)依然可以處理客戶端的請(qǐng)求。從技術(shù)上來(lái)講,Raft是一個(gè)管理復(fù)制日志(Replicated Log)的共識(shí)算法,復(fù)制日志是復(fù)制狀態(tài)機(jī)(RSM:Replicated State Machine)的組成部分。
復(fù)制狀態(tài)機(jī)是用于構(gòu)建分布式系統(tǒng)的一種比較基礎(chǔ)的架構(gòu)。它的主要構(gòu)成單元包括:包含命令序列的節(jié)點(diǎn)日志、共識(shí)模塊(例如Raft)和狀態(tài)機(jī)。
復(fù)制狀態(tài)機(jī)的工作原理如下:
客戶端向主導(dǎo)節(jié)點(diǎn)(Leader Node)發(fā)送包含命令的請(qǐng)求
主導(dǎo)節(jié)點(diǎn)將收到的請(qǐng)求追加到其日志中,并將該請(qǐng)求發(fā)送給所有的 跟隨節(jié)點(diǎn)(Follower Node)。跟隨節(jié)點(diǎn)也會(huì)將該請(qǐng)求追加到自身的日志中 并返回一個(gè)確認(rèn)消息
一旦主導(dǎo)節(jié)點(diǎn)收到大部分跟隨節(jié)點(diǎn)的確認(rèn)消息,就會(huì)將命令日志提交給其管理的狀態(tài)機(jī)。一旦主導(dǎo)節(jié)點(diǎn)提交了日志,跟隨節(jié)點(diǎn)也會(huì)將日志提交給自身管理的狀態(tài)機(jī)
主導(dǎo)節(jié)點(diǎn)向客戶端返回響應(yīng)結(jié)果
那么,Raft在復(fù)制狀態(tài)機(jī)架構(gòu)中扮演什么角色?
Raft的作用是確保跟隨節(jié)點(diǎn)的日志與主導(dǎo)節(jié)點(diǎn)的日志保持一致(即:日志復(fù)制),這樣整個(gè)分布式系統(tǒng)的行為看起來(lái)是一致的,即使部分節(jié)點(diǎn)出現(xiàn)故障也沒(méi)有影響。
另一個(gè)問(wèn)題,客戶端是否需要了解哪個(gè)是主導(dǎo)節(jié)點(diǎn)?
答案是NO,客戶端可以向任何一個(gè)節(jié)點(diǎn)發(fā)送請(qǐng)求,如果該節(jié)點(diǎn)是主導(dǎo)節(jié)點(diǎn),那么它會(huì)直接處理請(qǐng)求,否則的話,該節(jié)點(diǎn)會(huì)轉(zhuǎn)發(fā)請(qǐng)求給主導(dǎo)節(jié)點(diǎn)。
對(duì)于Raft算法而言,每個(gè)節(jié)點(diǎn)只能處于三個(gè)狀態(tài)之一:
跟隨狀態(tài):初始情況下,所有的節(jié)點(diǎn)都處于跟隨狀態(tài),也就是都是跟隨節(jié)點(diǎn)。一旦某個(gè)跟隨節(jié)點(diǎn)沒(méi)有正常通信,它就轉(zhuǎn)換為候選狀態(tài)(Candidate),也就是成為一個(gè)候選節(jié)點(diǎn)。跟隨節(jié)點(diǎn)的日志可以被主導(dǎo)節(jié)點(diǎn)重寫。
候選狀態(tài):處于候選狀態(tài)的節(jié)點(diǎn)會(huì)發(fā)起選舉,如果它收到集群中大多數(shù)成員的投票認(rèn)可,就轉(zhuǎn)換為主導(dǎo)狀態(tài)。
主導(dǎo)狀態(tài):處理客戶端請(qǐng)求并確保所有的跟隨節(jié)點(diǎn)具有相同的日志副本。主導(dǎo)節(jié)點(diǎn)不可以重寫其自身的日志。
如果候選節(jié)點(diǎn)發(fā)現(xiàn)已經(jīng)選出了主導(dǎo)節(jié)點(diǎn),它就會(huì)退回到跟隨狀態(tài)。同樣,如果主導(dǎo)節(jié)點(diǎn)發(fā)現(xiàn)另一個(gè)主導(dǎo)節(jié)點(diǎn)的任期(Term)值更高,它也會(huì)退回到跟隨狀態(tài)。
任期(Term)是一個(gè)單調(diào)遞增的整數(shù)值,用來(lái)標(biāo)識(shí)主導(dǎo)節(jié)點(diǎn)的管理周期。每個(gè)任期都從選舉開始,直到下一個(gè)任期之前。
Raft使用心跳機(jī)制來(lái)出發(fā)主導(dǎo)節(jié)點(diǎn)的選舉。當(dāng)節(jié)點(diǎn)啟動(dòng)后進(jìn)入跟隨狀態(tài),只要它能從主導(dǎo)節(jié)點(diǎn)或候選節(jié)點(diǎn)收到有效的RPC心跳消息,就會(huì)保持在跟隨狀態(tài)。主導(dǎo)節(jié)點(diǎn)會(huì)周期性發(fā)送心跳消息(沒(méi)有日志項(xiàng)的AppendEntries RPC消息)給所有的跟隨節(jié)點(diǎn)來(lái)維持其主導(dǎo)地位。如果某個(gè)跟隨節(jié)點(diǎn)在一段時(shí)間內(nèi)沒(méi)有收到心跳消息,就發(fā)生選舉超時(shí)事件,該節(jié)點(diǎn)就認(rèn)為目前沒(méi)有主導(dǎo)節(jié)點(diǎn)并發(fā)起選舉來(lái)選出新的主導(dǎo)節(jié)點(diǎn)。
要開始一個(gè)選舉,跟隨節(jié)點(diǎn)會(huì)遞增其當(dāng)前任期值并轉(zhuǎn)換到候選狀態(tài)。該節(jié)點(diǎn)首先給自己投一票,然后同時(shí)向其他節(jié)點(diǎn)發(fā)送請(qǐng)求投票的消息(RequestVote RPC消息)。
候選節(jié)點(diǎn)會(huì)保持在候選狀態(tài),直到以下事件發(fā)生:
該節(jié)點(diǎn)勝出選舉
其他節(jié)點(diǎn)勝出選舉
沒(méi)有節(jié)點(diǎn)勝出選舉
如果該節(jié)點(diǎn)收到大部分節(jié)點(diǎn)的投票認(rèn)可,就可以勝出選舉,那么該節(jié)點(diǎn)就轉(zhuǎn)換到主導(dǎo)狀態(tài)成為新的主導(dǎo)節(jié)點(diǎn)。注意:每個(gè)節(jié)點(diǎn)只能投一票。
如果同時(shí)也有其他節(jié)點(diǎn)宣布自己是主導(dǎo)節(jié)點(diǎn)并有更高的任期值,那么任期值高的節(jié)點(diǎn)成為新的主導(dǎo)節(jié)點(diǎn):
如果多個(gè)候選節(jié)點(diǎn)的得票情況相同,那么沒(méi)有勝出節(jié)點(diǎn)。
要避免出現(xiàn)這種情況,可以重新初始化選舉并確保每個(gè)節(jié)點(diǎn)的選舉超時(shí)時(shí)長(zhǎng)是隨機(jī)的,以避免跟隨節(jié)點(diǎn)同時(shí)進(jìn)入候選狀態(tài)。
一旦選出主導(dǎo)節(jié)點(diǎn),它就開始處理客戶端的請(qǐng)求。請(qǐng)求中包含有復(fù)制狀態(tài)機(jī)需要執(zhí)行的命令。主導(dǎo)節(jié)點(diǎn)將命令追加到自己的日志中,然后并行發(fā)送AppendEntriesRPC消息給所有跟隨節(jié)點(diǎn)復(fù)制這個(gè)新的日志項(xiàng)。當(dāng)新的日志項(xiàng)被安全復(fù)制后,主導(dǎo)節(jié)點(diǎn)會(huì)在自身的狀態(tài)機(jī)上執(zhí)行這個(gè)日志項(xiàng)里的命令,并將結(jié)果返回給客戶端。
如果跟隨節(jié)點(diǎn)崩潰、運(yùn)行緩慢或網(wǎng)絡(luò)發(fā)生丟包問(wèn)題,主導(dǎo)節(jié)點(diǎn)會(huì)無(wú)限重試發(fā)送AppendEntries RPC消息(即使它已經(jīng)向客戶端返回了響應(yīng)結(jié)果),直到所有的跟隨節(jié)點(diǎn)最終得到一致的日志副本。
當(dāng)發(fā)送AppendEntries RPC消息時(shí),主導(dǎo)節(jié)點(diǎn)會(huì)同時(shí)發(fā)送新日志項(xiàng)的前序日志項(xiàng)的序號(hào)和任期值。如果跟隨節(jié)點(diǎn)在自身日志中沒(méi)有發(fā)現(xiàn)相同的序號(hào)和任期值,就會(huì)拒絕新的日志項(xiàng)。因此如果pendEntries成功返回,主導(dǎo)節(jié)點(diǎn)就知道跟隨節(jié)點(diǎn)的日志與自己是完全一致的。
當(dāng)出現(xiàn)不一致情況時(shí),主導(dǎo)節(jié)點(diǎn)強(qiáng)制跟隨節(jié)點(diǎn)復(fù)制自己的日志。
基于Raft的排序服務(wù)替代了之前的Kafka排序服務(wù)。每個(gè)排序節(jié)點(diǎn)都有其自己的Raft復(fù)制狀態(tài)機(jī)來(lái)提交日志??蛻舳死肂roadcast RPC發(fā)送交易提議。Raft排序節(jié)點(diǎn)基于共識(shí)生成新的區(qū)塊,當(dāng)對(duì)等節(jié)點(diǎn)發(fā)送Deliver RPC時(shí),將區(qū)塊發(fā)送給對(duì)等節(jié)點(diǎn)。
Raft排序節(jié)點(diǎn)的工作流程如下:
交易(例如提議、配置更新)應(yīng)當(dāng)自動(dòng)路由到通道的當(dāng)前主導(dǎo)節(jié)點(diǎn)
主導(dǎo)節(jié)點(diǎn)檢查交易驗(yàn)證的配置序列號(hào)是否與當(dāng)前配置序列號(hào)一致,如果不一致的 話則執(zhí)行驗(yàn)證,并在驗(yàn)證失敗后駁回交易。通過(guò)驗(yàn)證后,主導(dǎo)節(jié)點(diǎn)將收到的交易傳入?yún)^(qū)塊切割模塊的Ordered方法,創(chuàng)建候選區(qū)塊
如果產(chǎn)生了新的區(qū)塊,主導(dǎo)排序節(jié)點(diǎn)將其應(yīng)用于本地的Raft有限狀態(tài)機(jī)(FSM)
有限狀態(tài)機(jī)將嘗試復(fù)制到足夠數(shù)量的排序節(jié)點(diǎn),以便提交區(qū)塊
區(qū)塊被寫入接收節(jié)點(diǎn)的本地賬本
每個(gè)通道都會(huì)運(yùn)行Raft協(xié)議的單獨(dú)實(shí)例。換句話說(shuō),有N個(gè)通道的網(wǎng)絡(luò),就有N個(gè)Raft集群,每個(gè)Raft集群都有自己的主導(dǎo)排序節(jié)點(diǎn)。
我們使用BYFN組件展示raft共識(shí)模塊的使用方法。BYFN包含5個(gè)排序節(jié)點(diǎn),2個(gè)組織4個(gè)對(duì)等節(jié)點(diǎn),以及可選的CouchDB。在configtx.yaml文件中給出了Raft排序服務(wù)的配置。
用下面的腳本命令啟動(dòng)默認(rèn)的go鏈碼和raft共識(shí),該腳本會(huì)自動(dòng)生成必要的密碼學(xué)數(shù)據(jù):
cd fabric-samples/first-network ./byfn.sh up -o etcdraft
查看排序服務(wù):
docker logs -f ordrer3.example.com
現(xiàn)在我們驗(yàn)證Raft的容錯(cuò)能力。
首先停掉Node3:
docker stop orderer3.example.com
然后停掉Node5:
docker stop orderer5.example.com
現(xiàn)在驗(yàn)證系統(tǒng)的有效性,可以看到系統(tǒng)依然可以正常響應(yīng)客戶端的請(qǐng)求:
以上是“hyperledger fabric中Raft共識(shí)插件的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!