基于Raft+區(qū)塊鏈的共識算法Raft設(shè)計(jì)與實(shí)現(xiàn)(畢業(yè)論文+程序源碼)
大家好,今天給大家介紹基于Raft+區(qū)塊鏈的共識算法Raft設(shè)計(jì)與實(shí)現(xiàn),文章末尾附有本畢業(yè)設(shè)計(jì)的論文和源碼下載地址哦。需要下載開題報(bào)告PPT模板及論文答辯PPT模板等的小伙伴,可以進(jìn)入我的博客主頁查看左側(cè)最下面欄目中的自助下載方法哦
文章目錄:
1、項(xiàng)目簡介
- 區(qū)塊鏈,作為目前火熱的比特幣的底層支撐技術(shù),融合了分布式數(shù)據(jù)存儲,P2P傳輸,共識算法,加密等各種計(jì)算機(jī)技術(shù)。這其中最為重要的就是共識算法,對于共有鏈等開放的網(wǎng)絡(luò)環(huán)境往往使用PoW,而對于私有鏈等相對封閉的網(wǎng)絡(luò)環(huán)境,由于所有節(jié)點(diǎn)都是可信任的,往往使用Raft或者Paxos。本文就主要圍繞區(qū)塊鏈共識算法這一點(diǎn)來對比常用算法的異同以及使用場景,并就Raft給出具體實(shí)現(xiàn)以便于理解區(qū)塊鏈在分布式環(huán)境下如何達(dá)成共識。其中實(shí)現(xiàn)了Raft的兩個(gè)核心模塊:領(lǐng)導(dǎo)選舉和日志復(fù)制。
2、資源詳情
項(xiàng)目難度:中等難度
適用場景:相關(guān)題目的畢業(yè)設(shè)計(jì)
配套論文字?jǐn)?shù):12940個(gè)字30頁
包含內(nèi)容:全套源碼+配整論文
開題報(bào)告、論文答辯、課題報(bào)告等ppt模板推薦下載方式:
3、關(guān)鍵詞
Raft,區(qū)塊鏈,共識算法,領(lǐng)導(dǎo)選舉,日志復(fù)制4、畢設(shè)簡介
提示:以下為畢業(yè)論文的簡略介紹,項(xiàng)目完整源碼及完整畢業(yè)論文下載地址見文末。
1 緒論
1.1 區(qū)塊鏈簡介
區(qū)塊鏈技術(shù)起源于2008年“中本聰”的一篇論文《比特幣: 一種點(diǎn)對點(diǎn)電子現(xiàn)金系統(tǒng)》,目前還未形成行業(yè)公認(rèn)的嚴(yán)格的區(qū)塊鏈定義。但是從狹義上來看,它就是一種按照時(shí)間順序?qū)?shù)據(jù)區(qū)塊以順序相連的方式組合成的一種鏈?zhǔn)綌?shù)據(jù)結(jié)構(gòu),有點(diǎn)類似于計(jì)算機(jī)科學(xué)里面的鏈表這樣的數(shù)據(jù)結(jié)構(gòu),只不過鏈表的每個(gè)節(jié)點(diǎn)(這里被稱作區(qū)塊)的結(jié)構(gòu)更加復(fù)雜,每個(gè)節(jié)點(diǎn)的連接方式也與鏈表不同。而從廣義上來看,區(qū)塊鏈實(shí)際是利用塊鏈?zhǔn)綌?shù)據(jù)結(jié)構(gòu)來驗(yàn)證與存儲數(shù)據(jù)、利用分布式節(jié)點(diǎn)共識算法來生成和更新數(shù)據(jù)、利用密碼學(xué)的方式保證數(shù)據(jù)傳輸和訪問的安全、利用由自動化腳本代碼組成的智能合約來編程和操作數(shù)據(jù)的一種全新的分布式基礎(chǔ)架構(gòu)與計(jì)算方式。
通俗一點(diǎn)理解的話,區(qū)塊鏈就是一個(gè)去中心化的分布式數(shù)據(jù)庫,為什么說它是數(shù)據(jù)庫呢?因?yàn)樗闹饕饔镁褪谴鎯π畔?,任何需要保存的信息,都可以寫入?yún)^(qū)塊鏈,也可以從里面讀取,可讀可寫因此區(qū)塊鏈?zhǔn)莻€(gè)數(shù)據(jù)庫。為什么說它是去中心化的呢?因?yàn)槿魏稳硕伎梢约茉O(shè)服務(wù)器,加入?yún)^(qū)塊鏈網(wǎng)絡(luò),成為里面的一個(gè)節(jié)點(diǎn),不同于現(xiàn)在的很多網(wǎng)絡(luò)都有個(gè)管理者,區(qū)塊鏈從設(shè)計(jì)之初就保證了沒有任何管理者,也不能被任何人控制,在這個(gè)網(wǎng)絡(luò)中沒有任何中心節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)都是平等的,保存著整個(gè)數(shù)據(jù)庫,你可以向任何一個(gè)節(jié)點(diǎn)讀寫數(shù)據(jù),最后所有節(jié)點(diǎn)都會同步從而保持區(qū)塊鏈網(wǎng)絡(luò)最終一致。
區(qū)塊鏈?zhǔn)疽鈭D,每個(gè)區(qū)塊遍布在世界各地,依靠網(wǎng)絡(luò)連接成鏈
區(qū)塊鏈?zhǔn)怯梢粋€(gè)個(gè)區(qū)塊組成的,它們連接成鏈,那么每個(gè)區(qū)塊究竟是什么樣的呢?它們又是如何連接成鏈的呢?
在區(qū)塊鏈網(wǎng)絡(luò)中,數(shù)據(jù)會以文件的形式被永久記錄,我們稱這些文件為區(qū)塊。一個(gè)區(qū)塊是一些或所有最新比特幣交易的記錄集,且未被其他先前的區(qū)塊記錄。它的具體結(jié)構(gòu)如下圖所示:
每個(gè)區(qū)塊都包括了一個(gè)被稱為魔法數(shù)的常數(shù)、區(qū)塊的大小、區(qū)塊頭、區(qū)塊所包含的交易數(shù)量及部分或所有的近期新交易。在每個(gè)區(qū)塊中,對整個(gè)區(qū)塊鏈起決定作用的是區(qū)塊頭。區(qū)塊頭的結(jié)構(gòu)如下圖所示:
概括來說,每個(gè)區(qū)塊主要包含兩部分,一個(gè)是區(qū)塊頭,也就是上面這張圖,它記錄著當(dāng)前區(qū)塊的元信息,另一個(gè)是區(qū)塊體,記錄著實(shí)際數(shù)據(jù)。每個(gè)區(qū)塊頭里面都包含著前一區(qū)塊的Hash,這樣子每次新來一個(gè)區(qū)塊,這個(gè)新區(qū)塊就通過這個(gè)Hash指向前一個(gè)區(qū)塊從來達(dá)到相連接成鏈的效果。
前面說過,區(qū)塊頭包含很多內(nèi)容,其中有當(dāng)前區(qū)塊體的哈希,還有上一個(gè)區(qū)塊的哈希。這意味著,如果當(dāng)前區(qū)塊體的內(nèi)容變了,或者上一個(gè)區(qū)塊的哈希變了,一定會引起當(dāng)前區(qū)塊的哈希改變。這一點(diǎn)對區(qū)塊鏈有重大意義。如果有人修改了一個(gè)區(qū)塊,該區(qū)塊的哈希就變了。為了讓后面的區(qū)塊還能連到它(因?yàn)橄乱粋€(gè)區(qū)塊包含上一個(gè)區(qū)塊的哈希),該人必須依次修改后面所有的區(qū)塊,否則被改掉的區(qū)塊就脫離區(qū)塊鏈了。由于區(qū)塊鏈中設(shè)計(jì)的計(jì)算很耗時(shí),短時(shí)間內(nèi)修改多個(gè)區(qū)塊幾乎不可能發(fā)生,除非有人掌握了全網(wǎng)51%以上的計(jì)算能力。因此,區(qū)塊鏈保證了自己的可靠性,數(shù)據(jù)一旦寫入,就無法被篡改。
正是因?yàn)樯厦娼榻B的種種技術(shù)特點(diǎn),區(qū)塊鏈才能支撐起以比特幣為代表的數(shù)字加密貨幣體系。對于區(qū)塊鏈來說,它的核心優(yōu)勢是去中心化, 能夠通過運(yùn)用數(shù)據(jù)加密、共識算法、分布式數(shù)據(jù)存儲和經(jīng)濟(jì)激勵等手段, 在分布式系統(tǒng)中實(shí)現(xiàn)基于去中心化信用的點(diǎn)對點(diǎn)交易,從而為中心化機(jī)構(gòu)普遍存在的高成本、低效率和數(shù)據(jù)存儲不安全等問題提供了解決方案。隨著比特幣近年來的快速發(fā)展與普及, 區(qū)塊鏈技術(shù)的研究與應(yīng)用也呈現(xiàn)爆發(fā)性增長趨勢,被認(rèn)為是下一代云計(jì)算的雛形, 有望像互聯(lián)網(wǎng)一樣徹底重塑人類社會活動形態(tài), 并實(shí)現(xiàn)從目前的信息互聯(lián)網(wǎng)向價(jià)值互聯(lián)網(wǎng)的轉(zhuǎn)變。
1.2 論文內(nèi)容安排
對于區(qū)塊鏈來說,它的基礎(chǔ)架構(gòu)模型如下圖所示:
一般來說,區(qū)塊鏈系統(tǒng)由數(shù)據(jù)層、網(wǎng)絡(luò)層、共識層、激勵層、合約層和應(yīng)用層組成。其中, 數(shù)據(jù)層封裝了底層數(shù)據(jù)塊和相關(guān)的數(shù)據(jù)加密等技術(shù); 網(wǎng)絡(luò)層則包括分布式組網(wǎng)機(jī)制、數(shù)據(jù)傳播和驗(yàn)證機(jī)制等; 共識層主要封裝節(jié)點(diǎn)的各類共識算法; 激勵層將經(jīng)濟(jì)因素集成到區(qū)塊鏈技術(shù)體系中來, 主要包括經(jīng)濟(jì)激勵的發(fā)行機(jī)制和分配機(jī)制等; 合約層主要封裝各類腳本、 算法和智能合約, 是區(qū)塊鏈可編程特性的基礎(chǔ); 應(yīng)用層則封裝了區(qū)塊鏈的各種應(yīng)用場景和案例。
本文是基于區(qū)塊鏈的共識算法Raft的實(shí)現(xiàn),主要關(guān)注的就是區(qū)塊鏈中最為重要的共識層,至于其他合約層,應(yīng)用層等不會涉及到。論文的主要安排如下:
第一章介紹區(qū)塊鏈的整體情況,主要涉及了區(qū)塊鏈的相關(guān)技術(shù)和發(fā)展情況。
第二章會重點(diǎn)關(guān)注區(qū)塊鏈的共識層,主要包括了共有鏈,私有鏈等常用的共識算法,對比分析各類共識算法的異同以及適用場景。
第三章會詳細(xì)介紹共識算法中的Raft,并給出Raft的具體的設(shè)計(jì)與實(shí)現(xiàn),最后通過MIT的測試框架對Raft進(jìn)行了整體的測試并衡量其性能。
第四章對項(xiàng)目與進(jìn)行了總結(jié),主要列出了在學(xué)習(xí)實(shí)現(xiàn)Raft遇到的一些問題以及如何解決的方案,總結(jié)了還有哪些需要改進(jìn)的地方。
2共識算法
區(qū)塊鏈?zhǔn)紫仁且粋€(gè)分布式系統(tǒng),由傳統(tǒng)的單節(jié)點(diǎn)結(jié)構(gòu)(CS模型)演變到多機(jī)的分布式系統(tǒng),最為重要的一個(gè)問題就是如何保證多機(jī)的數(shù)據(jù)一致性,從而保證系統(tǒng)達(dá)成共識。而這些往往是通過某些協(xié)議(或者是共識算法)來保證的。一般來說,共識算法可分為傳統(tǒng)的分布式一致性算法以及區(qū)塊鏈獨(dú)創(chuàng)的共識算法,在某些特定的場景下比如私有區(qū)塊鏈,使用傳統(tǒng)的分布式一致性算法效率會更高,效果會更好。因此,從某種意義上來說,傳統(tǒng)分布式一致性算法也是共識算法的子集,本章主要會討論以Raft,PBFT為代表的傳統(tǒng)分布式一致性共識算法和Pow,PoS等區(qū)塊鏈獨(dú)有共識算法的異同,以及他們分別適用于區(qū)塊鏈的什么場景。
2.1 傳統(tǒng)分布式一致性共識算法和區(qū)塊鏈獨(dú)有共識算法異同
相同點(diǎn):
Append Only,數(shù)據(jù)一旦寫入不可修改,只追加寫日志或者添加新區(qū)塊
少數(shù)服從多數(shù)原則,一旦大多數(shù)節(jié)點(diǎn)達(dá)成共識便可以判定系統(tǒng)達(dá)成共識,對于分離覆蓋的問題,一般都是長鏈覆蓋短鏈,多節(jié)點(diǎn)覆蓋少數(shù)節(jié)點(diǎn)日志
不同點(diǎn):
傳統(tǒng)分布式一致性算法大多不考慮拜占庭容錯(cuò)(Byzanetine Paxos除外),即假設(shè)所有節(jié)點(diǎn)只發(fā)生宕機(jī)、網(wǎng)絡(luò)故障等非人為問題,并不考慮惡意節(jié)點(diǎn)篡改數(shù)據(jù)的問題,而區(qū)塊鏈獨(dú)有共識算法幾乎都考慮了拜占庭容錯(cuò)
傳統(tǒng)分布式一致性算法是面向日志(數(shù)據(jù)庫)的,即更通用的情況,而區(qū)塊鏈共識模型面向交易的,所以從某種程度上來說,傳統(tǒng)分布式一致性共識算法有時(shí)候也可以算作區(qū)塊鏈共識模型的下面一層。
2.2 適用場景
區(qū)塊鏈分為三類,在貨幣發(fā)行的《區(qū)塊鏈:定義未來金融與經(jīng)濟(jì)新格局》一書中就有詳細(xì)介紹。主要共有鏈,私有鏈,行業(yè)鏈(聯(lián)盟鏈)。其中:
共有鏈:
開放生態(tài)的網(wǎng)絡(luò),世界上任何個(gè)體或者團(tuán)體都可以發(fā)送交易,且交易能夠獲得該區(qū)塊鏈的有效確認(rèn),任何人都可以參與其共識過程。公有區(qū)塊鏈?zhǔn)亲钤绲膮^(qū)塊鏈,也是應(yīng)用最廣泛的區(qū)塊鏈,各大bitcoins系列的虛擬數(shù)字貨幣均基于公有區(qū)塊鏈。
私有鏈:
封閉生態(tài)的網(wǎng)絡(luò),僅僅使用區(qū)塊鏈的總賬技術(shù)進(jìn)行記賬,可以是一個(gè)公司,也可以是個(gè)人,獨(dú)享該區(qū)塊鏈的寫入權(quán)限,本鏈與其他的分布式存儲方案沒有太大區(qū)別。
行業(yè)鏈(聯(lián)盟鏈):
半封閉生態(tài)的網(wǎng)絡(luò),由某個(gè)群體內(nèi)部指定多個(gè)預(yù)選的節(jié)點(diǎn)為記賬人,每個(gè)塊的生成由所有的預(yù)選節(jié)點(diǎn)共同決定(預(yù)選節(jié)點(diǎn)參與共識過程),其他接入節(jié)點(diǎn)可以參與交易,但不過問記賬過程(本質(zhì)上還是托管記賬,只是變成分布式記賬,預(yù)選節(jié)點(diǎn)的多少,如何決定每個(gè)塊的記賬者成為該區(qū)塊鏈的主要風(fēng)險(xiǎn)點(diǎn)),其他任何人可以通過該區(qū)塊鏈開放的API進(jìn)行限定查詢。
由于私有鏈?zhǔn)欠忾]生態(tài)的網(wǎng)絡(luò),也就是說使用傳統(tǒng)分布式一致性共識算法應(yīng)該是最優(yōu)的。而對于聯(lián)盟行業(yè)鏈其半封閉半開放特性,使用Delegated Proof of Stake是最優(yōu)的,也可以考慮以傳統(tǒng)一致性算法作為基礎(chǔ)加入拜占庭容錯(cuò)/安全防護(hù)機(jī)制進(jìn)行改進(jìn)。公有鏈PoW,PoS應(yīng)該是比較優(yōu)秀的選擇,比特幣就采用PoW共識算法。
2.3 各種共識算法
前面提過,對于私有鏈而言,由于是封閉生態(tài)的網(wǎng)絡(luò),里面的每個(gè)節(jié)點(diǎn)都是可信的,采用類似PoW,PoS等算法效率并不高,而采用Raft,PBFT,Paxos這樣傳統(tǒng)的分布式一致性共識算法往往會更好。對于傳統(tǒng)的分布式一致性共識算法,下面主要介紹Raft和PBFT,而對于Paxos,盡管也屬于傳統(tǒng)的分布式一致性共識算法,但是由于它難以理解,應(yīng)用于工程化,并且Raft算法本身就是對Paxos的一種簡化改進(jìn),有很多類似之處,因此Paxos不做介紹,有興趣的可以自己查閱相關(guān)資料。
類似于比特幣這樣子加密貨幣體系運(yùn)行的環(huán)境往往是共有鏈,他們是全球開發(fā)生態(tài)的網(wǎng)絡(luò),所要面臨的問題便異常的復(fù)雜,傳統(tǒng)的分布式一致性共識算法往往滿足不了,因此會使用PoW,PoS,DPOS等共識算法,我們僅對最常見的算法做簡單的介紹。
2.3.1 Raft
Raft是通過復(fù)制狀態(tài)機(jī)將狀態(tài)的一致性轉(zhuǎn)化為日志的一致性,簡單來說,就是對于N個(gè)數(shù)據(jù)庫,如果他們的初始狀態(tài)一致,以后進(jìn)行的操作一致性,那么最終的數(shù)據(jù)也肯定能保持一致性。
如下圖所示,復(fù)制狀態(tài)機(jī)是通過復(fù)制日志來實(shí)現(xiàn)的。每一臺服務(wù)器保存著一份日志,日志中包含一系列的命令(比如x = 3, y = x等),狀態(tài)機(jī)會按順序執(zhí)行這些命令。因?yàn)槊恳慌_計(jì)算機(jī)的狀態(tài)機(jī)都是確定的,所以每個(gè)狀態(tài)機(jī)的狀態(tài)都是相同的,執(zhí)行的命令是相同的,最后的執(zhí)行結(jié)果也就是一樣的了。
復(fù)制狀態(tài)機(jī)
Raft將服務(wù)器分為三種角色:Leader,F(xiàn)ollower,Candidate,并且可以互相轉(zhuǎn)換,它主要分為兩個(gè)過程,一個(gè)是領(lǐng)導(dǎo)人選舉,另一個(gè)日志復(fù)制。當(dāng)一個(gè)分布式系統(tǒng)啟動時(shí),Raft選舉出一個(gè)領(lǐng)導(dǎo)人,一旦領(lǐng)導(dǎo)人選舉好了,他便負(fù)責(zé)從客戶端接收日志并且將日志復(fù)制到其他機(jī)器上以保證分布式系統(tǒng)的一致性。對于Raft的更多細(xì)節(jié),包括領(lǐng)導(dǎo)人宕機(jī),網(wǎng)絡(luò)分割等等一系列問題會在第三章Raft的實(shí)現(xiàn)給出詳細(xì)介紹。
2.3.2 PBFT
對于Raft來說,它有個(gè)前提就是,不考慮拜占庭容錯(cuò),所謂的拜占庭問題討論的是一個(gè)系統(tǒng)里面存在少數(shù)節(jié)點(diǎn)作惡(也就是消息可能偽造)如何保持分布式系統(tǒng)達(dá)成共識。
在介紹該算法前,先簡單了解一下拜占庭問題,它是Leslie Lamport提出用來解釋一致性問題的一個(gè)虛構(gòu)模型。拜占庭是古代東羅馬帝國的首都,由于地域?qū)拸V,守衛(wèi)邊境的多個(gè)將軍(相當(dāng)于系統(tǒng)中的多個(gè)節(jié)點(diǎn))需要通過信使來傳遞消息,達(dá)成某些一致的決定。但由于將軍中可能存在叛徒(系統(tǒng)中節(jié)點(diǎn)出錯(cuò)),這些叛徒將努力向不同的將軍發(fā)送不同的消息,試圖會干擾一致性的達(dá)成。BFT算法便是用來解決以上問題的,只不過這個(gè)算法的復(fù)雜度過高一直受人詬病,直到PBFT算法將復(fù)雜度用指數(shù)級降到多項(xiàng)式級別才得到廣泛應(yīng)用。這個(gè)算法能夠保證失效節(jié)點(diǎn)不超過總數(shù)的1/3的情況下保證Safety和Liveness,即n >= 3f+1,其中n是系統(tǒng)中的總節(jié)點(diǎn)數(shù),f是允許出現(xiàn)故障的節(jié)點(diǎn)數(shù)。
舉個(gè)例子來說,有4個(gè)參與者,一個(gè)被選舉為軍長,3個(gè)師長。軍長接到總司令命令:向前行軍500公里。軍長就會給3個(gè)師長發(fā)命令該命令。3個(gè)師長收到消息后會執(zhí)行命令,并匯報(bào)結(jié)果。A,B師長說我在首都東500公里, C師長說我在首都東100公里。軍長總結(jié)3個(gè)師長的匯報(bào),發(fā)現(xiàn)首都以東500公里占多數(shù)(2票>1票),所以就會忽略C師長的匯報(bào)結(jié)果,給總司令匯報(bào)說,好了,現(xiàn)在部隊(duì)是在首都東500公里了。這就是PBFT算法。
client:請求(request)自愿者,上例中指總司令。
replica:副本,所有參與提供服務(wù)的節(jié)點(diǎn),上例指軍長和師長
primary:承擔(dān)起提供服務(wù)主要職責(zé)的節(jié)點(diǎn),上例是軍長
backup:其他副本,但相對于primary角色。上例指師長。
view:處于存在primary-bakup場景中的相對穩(wěn)定的關(guān)系,叫視圖。
1.request階段:client向primary節(jié)點(diǎn)發(fā)送請求,比如總司令給軍長下命令。
2.pre-prepare階段:primary節(jié)點(diǎn)向所有backup節(jié)點(diǎn)發(fā)送預(yù)準(zhǔn)備消息,比如軍長對各位師長說:現(xiàn)在是我的時(shí)代(視圖),我是軍長,所有人都得聽我的,現(xiàn)在公布總司令的命令。
3.prepare階段:backup節(jié)點(diǎn)i接受了預(yù)準(zhǔn)備消息,則進(jìn)入準(zhǔn)備階段。在準(zhǔn)備階段的同時(shí),該節(jié)點(diǎn)向所有replica節(jié)點(diǎn)發(fā)送準(zhǔn)備消息,并且將預(yù)準(zhǔn)備消息和準(zhǔn)備消息寫入自己的消息日志。
4.commit階段:replica節(jié)點(diǎn)收到2f個(gè)從不同副本節(jié)點(diǎn)發(fā)來一致的預(yù)準(zhǔn)備消息,一共2f+1個(gè)一致的預(yù)準(zhǔn)備消息確認(rèn)了消息的正確性,然后按照序號n依次執(zhí)行請求。
5 reply階段:結(jié)果反饋。
2.3.3 PoW
前面提到的Raft和PBFT算法往往應(yīng)用于私有鏈,而當(dāng)面對情況異常復(fù)雜的共有鏈的時(shí)候,往往采用基于概率,經(jīng)濟(jì)博弈的共識,在理論上共識是可能被推翻的,只是攻擊者要付出的代價(jià)隨著時(shí)間越來越大,例如比特幣網(wǎng)絡(luò)中所有礦工都必須付出挖礦的代價(jià),進(jìn)行算力消耗,一旦失敗,這些算力都會成為沉默成本。以PoW等代表的就是這樣的共識算法。PoW共識算法要求通過計(jì)算來猜測一個(gè)數(shù)值(nonce),使得交易數(shù)據(jù)的內(nèi)容Hash滿足規(guī)定的條件。一個(gè)符合要求的Hash由N個(gè)前導(dǎo)零構(gòu)成,零的個(gè)數(shù)取決于網(wǎng)絡(luò)調(diào)節(jié)的難度值。要得到合理的Hash需要經(jīng)過大量嘗試計(jì)算,計(jì)算時(shí)間取決于機(jī)器的哈希運(yùn)算速度。當(dāng)某個(gè)節(jié)點(diǎn)提供出一個(gè)合理的Hash值,說明該節(jié)點(diǎn)確實(shí)經(jīng)過了大量的嘗試計(jì)算,這樣的機(jī)制能夠保證整個(gè)系統(tǒng)只有極少數(shù)的節(jié)點(diǎn)能夠?qū)懭胄聟^(qū)塊,如果有人想要惡意破壞,需要付出大量的經(jīng)濟(jì)成本,這幾乎是超過了可能帶來的好處,從而保證數(shù)據(jù)的一致性。如果同一時(shí)間遇到數(shù)據(jù)分叉,也就是不止一個(gè)數(shù)據(jù)寫入,區(qū)塊鏈能夠自動保證選擇長的那條鏈繼續(xù)進(jìn)行下去,而拋棄短鏈,這樣子就保證了區(qū)塊鏈的最長鏈一致性。
2.3.4 PoS
PoW能夠解決區(qū)塊鏈中的共識問題,但是有一點(diǎn),為了獲取那個(gè)滿足要求的Hash,只能進(jìn)行大量的無意義的暴力計(jì)算,這十分浪費(fèi)計(jì)算機(jī)資源。為了改進(jìn)這個(gè)缺點(diǎn),引入了PoS算法。它有點(diǎn)類似于現(xiàn)實(shí)生活中的股東機(jī)制,擁有股份越多的人越容易獲得記賬權(quán)。典型的過程是通過保證金來對賭合法的塊成為新區(qū)塊,收益為抵押資本的利息和交易服務(wù)費(fèi),提供的保證金越多獲得的記賬權(quán)的概率越大,合法記賬者獲得收益。
2.3.5 DPoS
PoS避免了無意義的計(jì)算導(dǎo)致的資源浪費(fèi),但依據(jù)權(quán)益結(jié)余來選擇,會導(dǎo)致首富賬戶的權(quán)力過大,可能支配記賬權(quán)。DPOS與POS原理相同,主要區(qū)別在于節(jié)點(diǎn)選舉若干代理人,由代理人驗(yàn)證和記賬。它的中文名叫做股份授權(quán)證明機(jī)制(又稱受托人機(jī)制),原理是讓每一個(gè)持有比特股的人進(jìn)行投票,由此產(chǎn)生101位代表 , 任何一個(gè)持幣用戶都可以參與到投票和競選受托人這兩個(gè)過程中。用戶可以隨時(shí)投票、撤票,每個(gè)用戶投票的權(quán)重和自己的持幣量成正比。投票和撤票可以隨時(shí)進(jìn)行,在每一輪(round)選舉結(jié)束后,得票率最高的101(一般為101,也可以是其他數(shù)字)個(gè)用戶則成為該項(xiàng)目的受托人,負(fù)責(zé)打包區(qū)塊、維持系統(tǒng)的運(yùn)轉(zhuǎn)并獲得相應(yīng)的獎勵。
選舉的根本目的,是通過每個(gè)人的投票選舉出社區(qū)里對項(xiàng)目發(fā)展和運(yùn)行最有利的101個(gè)用戶。這101個(gè)用戶的服務(wù)器節(jié)點(diǎn)既可以高效維護(hù)系統(tǒng)的運(yùn)轉(zhuǎn),而他們也會貢獻(xiàn)自己的能力促進(jìn)區(qū)塊鏈項(xiàng)目的發(fā)展,這有點(diǎn)類似于我國的‘人民代表’制度(但是周期更短、效率更高)。通過這種方式,既達(dá)到了去中心化的選舉共識,又保證了整個(gè)系統(tǒng)的運(yùn)行效率和減少能源浪費(fèi)。
3 Raft的設(shè)計(jì),實(shí)現(xiàn)和測試
第二章對于區(qū)塊鏈各種常見的共識算法做了一個(gè)簡單概括,并分析了他們的應(yīng)用場景以及異同。這一章會詳細(xì)介紹其中的一種共識算法Raft,并給出具體的設(shè)計(jì),實(shí)現(xiàn)和測試方案。
3.1算法介紹
Raft源自于2013年的一篇論文《In Search of an Understandable Consensus Algorithm(Extended Version)》,它主要解決了在分布式環(huán)境下如何保證數(shù)據(jù)的一致性從而讓系統(tǒng)達(dá)成共識。在這之前,Paxos算法在分布式環(huán)境一致性相關(guān)問題占領(lǐng)了統(tǒng)治地位,絕大多數(shù)的一致性實(shí)現(xiàn)都是基于Paxos或者受其影響。然而Paxos的算法最大的缺點(diǎn)就是難以理解并且難以運(yùn)用于工程實(shí)踐,而Raft算法正是在這種情況下應(yīng)運(yùn)而生。它不僅能滿足分布式環(huán)境一致性的需求,更重要的是它比其他算法更簡單且更易于理解,能廣泛的應(yīng)用于工程實(shí)踐,同時(shí)它的安全性和效率與其他算法也不相上下。
為了滿足算法的可理解性和可實(shí)踐性,Raft算法使用了兩種通用的技術(shù)。第一個(gè)技術(shù)就是問題分解:將復(fù)雜的問題分解成幾個(gè)相對獨(dú)立的,可被解決的和可理解的子問題。例如,Raft 算法被分成領(lǐng)導(dǎo)選舉,日志復(fù)制,安全性等幾個(gè)子問題。第二個(gè)方法是通過減少狀態(tài)的數(shù)量來簡化狀態(tài)空間,使得系統(tǒng)更加連貫并且盡可能消除不確定性,比如 Raft 限制了使日志之間不一致的方式。
服務(wù)器的狀態(tài)圖
一個(gè) Raft 集群包括n臺服務(wù)器,必須保證至少n/2+1臺機(jī)器正常,比如對于一個(gè)5 服務(wù)器集群,最多能夠容忍 2 臺機(jī)器不能正常工作,剩余的3臺機(jī)器必須正常,這樣子整個(gè)系統(tǒng)才能保持正常服務(wù)。在任意的時(shí)間,每一個(gè)服務(wù)器一定會處于以下三種狀態(tài)中的一個(gè):領(lǐng)導(dǎo)人(Leader)、候選人(Candidate)、追隨者(Follower)。在正常情況下,只有一個(gè)服務(wù)器是領(lǐng)導(dǎo)人,剩下的服務(wù)器是追隨者。追隨者們是被動的:他們不會發(fā)送任何請求,只是響應(yīng)來自領(lǐng)導(dǎo)人和候選人的請求。如果追隨者沒有收到任何消息,它會成為一個(gè)候選人并且開始一次選舉,收到大多數(shù)服務(wù)器投票的候選人會成為新的領(lǐng)導(dǎo)人。而對于領(lǐng)導(dǎo)人, 他會來處理所有來自客戶端的請求(如果一個(gè)客戶端與追隨者進(jìn)行通信,追隨者會將信息發(fā)送給領(lǐng)導(dǎo)人)。領(lǐng)導(dǎo)人會一直保持領(lǐng)導(dǎo)人的狀態(tài)直到它宕機(jī),這樣子會重新開始一次選舉選出領(lǐng)導(dǎo)人重復(fù)以上過程。上面服務(wù)器的狀態(tài)圖很好的說明了這個(gè)過程。
如上圖所示,Raft 算法將時(shí)間劃分成為任意不同長度的任期(term)。任期用連續(xù)的數(shù)字進(jìn)行表示。每一個(gè)任期的開始都是領(lǐng)導(dǎo)選舉(election),在成功選舉之后,一個(gè)領(lǐng)導(dǎo)人會在任期內(nèi)管理整個(gè)集群(normal operation)。在某些情況下(no emerging leader),選票會被瓜分,有可能沒有選出領(lǐng)導(dǎo)人,那么,將會開始另一個(gè)任期,并且立刻開始下一次選舉。Raft 算法保證在給定的一個(gè)任期最少要有一個(gè)領(lǐng)導(dǎo)人。
Raft中的服務(wù)器通過RPC來通信,基本的 Raft僅需要 2 種 RPC。RequestVote RPC 是候選人在選舉過程中觸發(fā)的,AppendEntries RPC 是領(lǐng)導(dǎo)人觸發(fā)的。
3.1.1 領(lǐng)導(dǎo)選舉
Raft 使用心跳機(jī)制(heartbeat)來觸發(fā)領(lǐng)導(dǎo)人的選取。當(dāng)服務(wù)器啟動時(shí),所有服務(wù)器會初始化為追隨者狀態(tài)。服務(wù)器會一直保持這樣的狀態(tài)只要它們能夠收到來自領(lǐng)導(dǎo)人或者候選人的有效 RPC。領(lǐng)導(dǎo)人會向所有追隨者周期性發(fā)送心跳(heartbeat,沒有日志項(xiàng)的 AppendEntries RPC)來避免其他人選舉。如果某個(gè)追隨者在一個(gè)周期內(nèi)沒有收到心跳信息,就叫做選舉超時(shí)(election timeout),然后它就會假設(shè)沒有領(lǐng)導(dǎo)人并且開始一次選舉來選出一個(gè)新的領(lǐng)導(dǎo)人。
為了開始選舉,一個(gè)追隨者會自增它的當(dāng)前任期并且轉(zhuǎn)換狀態(tài)為候選人。然后,它會給自己投票并且給集群中的其他服務(wù)器發(fā)送 RequestVote RPC。有以下下列三種可能性會發(fā)生:
1.它贏得了選舉;
2.另一臺服務(wù)器贏得了選舉;
3.一段時(shí)間后沒有任何一臺服務(wù)器贏得了選舉
對于1,一個(gè)候選人如果在一個(gè)任期內(nèi)收到了來自集群中大多數(shù)服務(wù)器的投票就會贏得選舉。在一個(gè)任期內(nèi),一臺服務(wù)器最多能給一個(gè)候選人投票。一旦有候選人贏得了選舉,它就會成為領(lǐng)導(dǎo)人。然后它會像其他服務(wù)器發(fā)送心跳信息來建立自己的領(lǐng)導(dǎo)地位。
對于2,當(dāng)一個(gè)候選人等待別人的選票時(shí),它有可能會收到來自其他服務(wù)器發(fā)來的聲明其為領(lǐng)導(dǎo)人的 AppendEntries RPC。如果這個(gè)領(lǐng)導(dǎo)人的任期比當(dāng)前候選人的當(dāng)前任期要大,則候選人認(rèn)為該領(lǐng)導(dǎo)人合法,并且轉(zhuǎn)換自己的狀態(tài)為追隨者。如果在這個(gè) RPC 中的任期小于候選人的當(dāng)前任期,則候選人會拒絕此次 RPC, 繼續(xù)保持候選人狀態(tài)。
對于3,一個(gè)候選人既沒有贏得選舉也沒有輸?shù)暨x舉:如果許多追隨者在同一時(shí)刻都成為了候選人,選票會被分散,可能沒有候選人能獲得大多數(shù)的選票。當(dāng)這種情形發(fā)生時(shí),每一個(gè)候選人都會超時(shí),并且通過自增任期號和發(fā)起另一輪 RequestVote RPC 來開始一輪新的選舉。為了盡量避免這種情況發(fā)生甚至無限循環(huán)下去,Raft 使用隨機(jī)的選舉超時(shí)時(shí)間來保證。選舉超時(shí)時(shí)間是在一個(gè)固定的間隔內(nèi)隨機(jī)選出來的(例如,150~300ms)。這種機(jī)制使得在大多數(shù)情況下只有一個(gè)服務(wù)器會率先超時(shí),它會在其它服務(wù)器超時(shí)之前贏得選舉并且向其它服務(wù)器發(fā)送心跳信息。同樣的機(jī)制被用于選票一開始被瓜分的情況下。每一個(gè)候選人在開始一次選舉的時(shí)候會重置一個(gè)隨機(jī)的選舉超時(shí)時(shí)間,在超時(shí)進(jìn)行下一次選舉之前一直等待。這能夠減小在新的選舉中一開始選票就被瓜分的可能性。
3.1.2 日志復(fù)制
一旦選出了領(lǐng)導(dǎo)人,它就開始接收客戶端的請求。每一個(gè)客戶端請求都包含一條需要被復(fù)制狀態(tài)機(jī)(replicated state machine)執(zhí)行的命令(command)。領(lǐng)導(dǎo)人把這條命令寫入到日志中去,然后并行的向其他服務(wù)器發(fā)起 AppendEntries RPC ,要求其它服務(wù)器復(fù)制這個(gè)條目。一旦這個(gè)條目被安全的復(fù)制之后,領(lǐng)導(dǎo)人會將這個(gè)條目應(yīng)用到它的狀態(tài)機(jī)中并且會向客戶端返回執(zhí)行結(jié)果。
每個(gè)日志條目存儲著一條被狀態(tài)機(jī)執(zhí)行的命令和當(dāng)這條日志條目被領(lǐng)導(dǎo)人接收時(shí)的任期號。日志條目中的任期號用來檢測在不同服務(wù)器上日志的不一致性,它用于檢測日志條目的是否是最新的。每個(gè)日志條目也包含一個(gè)整數(shù)索引來表示它在日志中的位置。具體如下圖所示:
日志圖
領(lǐng)導(dǎo)人決定什么時(shí)候?qū)⑷罩緱l目應(yīng)用到狀態(tài)機(jī)是安全的;這種條目被稱為可被提交狀態(tài)(commited)。Raft 保證可被提交(commited)的日志條目是持久化的并且最終會被所有可用狀態(tài)機(jī)執(zhí)行。一旦被領(lǐng)導(dǎo)人創(chuàng)建的條目已經(jīng)復(fù)制到了大多數(shù)的服務(wù)器上,這個(gè)條目就稱為commited狀態(tài)。
Raft對于日志必須要滿足以下兩個(gè)特性:第一,如果不同日志中的兩個(gè)條目擁有相同的索引和任期號,那么他們存儲了相同的指令。第二,如果不同日志中的兩個(gè)條目擁有相同的索引和任期號,那么他們之前的所有日志條目也都相同。這是通過AppendEntries RPC執(zhí)行的一致性檢查實(shí)現(xiàn)的,在發(fā)送 AppendEntries RPC 的時(shí)候,領(lǐng)導(dǎo)者會將前一個(gè)日志條目的索引位置和任期號包含在里面。如果 跟隨者在它的日志中找不到包含相同索引位置和任期號的條目,那么他就會拒絕該新的日志條目。因此,每當(dāng) AppendEntries RPC 返回成功時(shí),leader 就知道 follower 的日志一定和自己相同。
對于正常情況下,leader 和 follower 的日志總會保持一致,然而一旦領(lǐng)導(dǎo)人崩潰就會可能導(dǎo)致日志不一致。為了保證跟隨者和領(lǐng)導(dǎo)的日志一致性,領(lǐng)導(dǎo)者需要找到追隨者同它的日志一致的地方,然后刪除追隨者在該位置之后的條目,然后將自己在該位置之后的條目發(fā)送給追隨者。這些操作都在 AppendEntries RPC 進(jìn)行一致性檢查時(shí)完成。領(lǐng)導(dǎo)人給每一個(gè)追隨者維護(hù)了一個(gè)nextIndex,它表示領(lǐng)導(dǎo)人將要發(fā)送給該追隨者的下一條日志條目的索引。當(dāng)一個(gè)領(lǐng)導(dǎo)人被選舉出來時(shí),它會將nextIndex初始化為它的最新的日志條目索引數(shù)+1。如果一個(gè)追隨者的日志和領(lǐng)導(dǎo)者的不一致,AppendEntries 一致性檢查會在下一次 AppendEntries RPC 時(shí)返回失敗。在失敗之后,領(lǐng)導(dǎo)人會將nextIndex遞減然后重試 AppendEntries RPC。最終nextIndex會達(dá)到一個(gè)領(lǐng)導(dǎo)人和追隨者日志一致的地方。這時(shí)會刪除追隨者中沖突的日志條目,并且添加所缺少的領(lǐng)導(dǎo)人的日志條目。這樣子 AppendEntries 一旦返回成功,追隨者和領(lǐng)導(dǎo)人的日志就保持一致了。
3.2算法設(shè)計(jì)與實(shí)現(xiàn)
3.2.1準(zhǔn)備工作
Raft算法可以使用多種語言來實(shí)現(xiàn),比如C++,Go,Python,Java等等,在這里,我們使用Go語言來實(shí)現(xiàn),原因如下:Go是一門自帶垃圾回收,類型安全的語言,它對多線程有著良好的支持(Goroutine),還包含著一個(gè)十分精簡的RPC庫可以直接使用,這些能夠幫助我們更好的實(shí)現(xiàn)Raft專注于算法邏輯而不必過分的操心諸如申請釋放內(nèi)存,網(wǎng)絡(luò)通信,并發(fā)編程的很多細(xì)節(jié)。同時(shí),MIT6.824課程提供一套基于Go語言的Raft測試框架,這套測試框架提供了算法實(shí)現(xiàn)的關(guān)鍵接口說明,因此這能夠減小算法實(shí)現(xiàn)和測試的難度,也提高了算法測試的準(zhǔn)確性。
所以,基于上述原因,最后實(shí)驗(yàn)的環(huán)境是Linux采用Go語言設(shè)計(jì),實(shí)現(xiàn)和測試Raft算法,同時(shí)需要下載配置MIT6.824課程自帶的一套測試框架。我們需要完成如下幾步:
- 安裝Go語言和Git
sudo apt-get install golang-go
sudo apt-get install git - 下載和配置Raft測試框架
git clone git://g.csail.mit.edu/6.824-golabs-2018 6.824
cd 6.824
export “GOPATH= P W D " c d " PWD" cd " PWD"cd"GOPATH/src/raft”
上述步驟執(zhí)行成功之后,基本的開發(fā)環(huán)境就配置好了。在Raft算法具體實(shí)現(xiàn)之前我們需要再做一些準(zhǔn)備工作。Raft算法是用來保證分布式系統(tǒng)的多臺機(jī)器的一致性的共識算法,這其中必不可少的就是網(wǎng)絡(luò)編程和并發(fā)編程,Go語言對這兩點(diǎn)有著非常好的支持,這也就是為什么使用Go語言來完成Raft的重要原因。
Raft使用RPC來完成網(wǎng)絡(luò)通信,RPC叫遠(yuǎn)程過程調(diào)用,它能夠讓我們像調(diào)用本地服務(wù)一樣調(diào)用遠(yuǎn)程服務(wù),屏蔽了網(wǎng)絡(luò)通信這些細(xì)節(jié),MIT6.824的測試框架提供了一套簡潔的RPC接口,而不需要自己實(shí)現(xiàn),在Raft中如果需要使用AppendEntries RPC或者RequestVote RPC只需要這樣調(diào)用:
func (rf *Raft) sendRequestVote(server int, args RequestVoteArgs, reply *RequestVoteReply) bool
{
ok := rf.peers[server].Call("Raft.RequestVote", args, reply)
return ok
}
func (rf *Raft) sendAppendEntries(server int, args AppendEntryArgs, reply *AppendEntryReply) bool
{
ok := rf.peers[server].Call("Raft.AppendEntries", args, reply)
return ok
}
其中,sever定位具體哪個(gè)sever發(fā)出的RPC請求,args表示請求參數(shù),reply表示回復(fù)結(jié)果,Call表示調(diào)用RPC接口,第一個(gè)字符串參數(shù)表示調(diào)用的函數(shù)名。
Raft中另一個(gè)重要的基礎(chǔ)知識就是并發(fā)編程,Go語言提供了很好的支持。在多線程環(huán)境下,如何避免臨界區(qū),一個(gè)常見的方法就是加鎖,但是Go提供了一套類似C++RAII的自動管理資源的方式:
mutex.Lock()
defer mutex.Unlock()
// 此處是多線程環(huán)境下需要讀寫的數(shù)比如i++
這樣子能夠避免了程序異常Crash可能的死鎖,同時(shí)Go自己還獨(dú)具特色的提供了一套Goroutine和Channel機(jī)制來保證多線程之間共享變量的控制。
func Say(str string, done chan int) {
fmt.Println(str)
time.Sleep(3 * time.Second)
done<-1
}
func main() {
done := make(chan int)
go Say("hello", done)
<-done
}
在Go語言,開啟一個(gè)線程執(zhí)行相應(yīng)的操作,十分簡潔,只需要寫go fun(),每個(gè)線程操作著自己的變量,因此無需同步,如果需要操作共享變量,則通過channel來傳遞,Go的設(shè)計(jì)哲學(xué)就在于此:不要通過共享內(nèi)存來通信,而應(yīng)通過通信來共享內(nèi)存。在上面的例子,主線程在main函數(shù)中執(zhí)行,通過go Say開啟另一個(gè)線程執(zhí)行,打印str并且sleep 3s然后通過done告訴主線程完成,主線程的channel通過<-done保證其他線程已經(jīng)執(zhí)行完,如果其他線程沒有執(zhí)行完就一直阻塞。
3.2.2 具體設(shè)計(jì)與實(shí)現(xiàn)
Raft算法的基本流程是初始化各個(gè)節(jié)點(diǎn)(Raft結(jié)構(gòu)),開始領(lǐng)導(dǎo)選舉,一旦領(lǐng)導(dǎo)選舉成功,接受客戶端請求,分發(fā)日志要求各節(jié)點(diǎn)復(fù)制日志,最后達(dá)成commited狀態(tài),一旦領(lǐng)導(dǎo)者宕機(jī)就需要重新選舉,重復(fù)以上過程。流程圖如下:
首先是Raft的初始化,根據(jù)論文上的說明,一個(gè)Raft節(jié)點(diǎn)至少需要保存以下狀態(tài):
因此,Raft的數(shù)據(jù)結(jié)構(gòu)定義為如下:
type Raft struct {
mu sync.Mutex
peers []*labrpc.ClientEnd // 用于保存集群里的所有機(jī)器的數(shù)組
persister *Persister // 用于持久化
me int // 自己
// Persistent state on all servers
currentTerm int
votedFor int
logs []LogEntry
// Volatile state on all servers
commitIndex int
lastApplied int
// Volatile state on leaders
nextIndex []int
matchIndex []int
voteNum int // 統(tǒng)計(jì)投票的票數(shù)
state string
applyCh chan ApplyMsg
timer *time.Timer // 用于設(shè)置定時(shí)器
}
剛開始需要調(diào)用Make函數(shù)初始化Raft結(jié)構(gòu),初始化完畢,此時(shí)所有的節(jié)點(diǎn)狀態(tài)都處于跟隨者,經(jīng)過一段時(shí)間(一般是150ms到300ms的某個(gè)隨機(jī)值),就會有一個(gè)節(jié)點(diǎn)開始發(fā)起選舉,它先回切換到候選人的身份,然后并行的向集群內(nèi)的多個(gè)節(jié)點(diǎn)發(fā)送RequestVote RPC。關(guān)鍵代碼如下:
rf.state = CANDIDATE
rf.currentTerm += 1
rf.votedFor = rf.me
rf.voteNum = 1
rf.persist()
for server := 0; server < len(rf.peers); server++ {
if server == rf.me {
continue
}
// ……
// 每個(gè)節(jié)點(diǎn)開啟一個(gè)線程發(fā)送RPC請求
go func(server int, args RequestVoteArgs) {
var reply RequestVoteReply ok := rf.sendRequestVote(server, args, &reply)
if ok {
rf.handleVoteResult(reply)
}
}(server, args)
}
一旦領(lǐng)導(dǎo)選舉成功后,整個(gè)Raft集群就處于服務(wù)狀態(tài),如果有client發(fā)送一次請求,比如x = 8,此時(shí)領(lǐng)導(dǎo)將這條命令寫入Log,并在下一次AppendEntries RPC中分發(fā)到各個(gè)節(jié)點(diǎn)要求它們復(fù)制,一旦大多數(shù)節(jié)點(diǎn)復(fù)制成功,這條日志就會處于commited狀態(tài)。
func (rf *Raft) Start(command interface{}) (int, int, bool) {
rf.mu.Lock()
defer rf.mu.Unlock()
index := -1
term := -1
isLeader := false
nlog := LogEntry{command, rf.currentTerm}
if rf.state != LEADER {
return index, term, isLeader
}
isLeader = (rf.state == LEADER)
rf.logs = append(rf.logs, nlog)
index = len(rf.logs)
term = rf.currentTerm
rf.persist()
return index, term, isLeader
}
如上,Leader調(diào)用Start函數(shù)接受一條命令并寫入日志后,并在下一次AppendEntries RPC中將這條日志分發(fā)到所有的跟隨者。
func (rf *Raft) sendAppendEntriesToAllFollowers() {
for i := 0; i < len(rf.peers); i++ {
if i == rf.me {
continue
}
// ……
// 每個(gè)節(jié)點(diǎn)開啟一個(gè)線程發(fā)送RPC請求
go func(server int, args AppendEntryArgs) {
var reply AppendEntryReply
ok := rf.sendAppendEntries(server, args, &reply)
if ok {
rf.handleAppendEntries(server, reply)
}
}(i, args)
}
}
在這里,sendAppendEntries(server, args, &reply)用于發(fā)送個(gè)某個(gè)sever的AppendEntries RPC請求,它調(diào)用了AppendEntries函數(shù),保證了日志的一致性。
3.3算法的測試
在前一節(jié),完成了算法的設(shè)計(jì)和實(shí)現(xiàn),并給出了關(guān)鍵部分的代碼,在這一節(jié),主要給出了Raft算法的測試,在這里使用MIT 6.824提供的一套測試框架,因?yàn)镽aft算法如果要應(yīng)用于分布式系統(tǒng)的話,不得不面對網(wǎng)絡(luò)通信,RPC框架,并發(fā)編程等等這些細(xì)節(jié),這給算法的測試帶來了很多的不確定性,同時(shí),在一個(gè)大規(guī)模的分布式系統(tǒng),網(wǎng)絡(luò)是異常復(fù)雜的,出現(xiàn)的問題很多時(shí)候是很難以模擬的,測試的覆蓋率也是很難保證的,因此為了專注于算法的設(shè)計(jì)與實(shí)現(xiàn),MIT6.824提供的這套測試框架為我們模擬一套基于channel機(jī)制的RPC框架,這樣不僅避免重復(fù)造輪子編寫RPC框架,同時(shí)基于channel模擬的RPC框架能夠盡量模擬出復(fù)雜的網(wǎng)絡(luò)動態(tài),比如機(jī)器的宕機(jī)重啟,網(wǎng)絡(luò)分割等等。
在測試之前,需要對于分布式環(huán)境進(jìn)行模擬,構(gòu)建出一套多臺服務(wù)器的集群以測試Raft算法。測試框架提供了以下接口:
省略
4 結(jié)論
這次畢業(yè)設(shè)計(jì)的出發(fā)點(diǎn)是為了工作做打下基礎(chǔ),我所在的部門是做分布式CDN的,今年將開始做區(qū)塊鏈相關(guān)的內(nèi)容,因此本次畢設(shè)定下的題目就是基于區(qū)塊鏈的Raft共識算法的實(shí)現(xiàn),當(dāng)然Raft不僅僅應(yīng)用于私有鏈,更廣泛運(yùn)用于分布式系統(tǒng)。
通過這次畢業(yè)設(shè)計(jì),我學(xué)到了很多東西,最為基礎(chǔ)的就是學(xué)習(xí)了Raft算法,然而在學(xué)習(xí)的過程中,讓我對分布式系統(tǒng)的基礎(chǔ)知識有了一些初步的了解,同時(shí)在實(shí)現(xiàn)Raft算法的過程中,學(xué)習(xí)到了Go語言的網(wǎng)絡(luò)編程,并發(fā)編程,RPC等,通過Raft算法以點(diǎn)到面的讓我了解了區(qū)塊鏈的各種共識機(jī)制以及對應(yīng)的應(yīng)用場景。
當(dāng)然,限于時(shí)間和能力所限,我只完成了Raft算法的兩個(gè)核心部分,領(lǐng)導(dǎo)選舉和日志復(fù)制,而日志壓縮和配置更新只是簡單了解,并未實(shí)現(xiàn),希望能在以后繼續(xù)完善并且優(yōu)化。
總體來說,這是一次對我意志力、學(xué)習(xí)能力的考驗(yàn),是對我編程技能和解決問題能力的一次提升,會對我將來學(xué)習(xí)和工作生活有非常大的幫助。
致 謝
省略
參 考 文 獻(xiàn)
[1] Robert Morris, Malte Schwarzkopf . MIT 6.824: Distributed Systems 2018.2
https://pdos.csail.mit.edu/6.824/
[2] 楊保華, 陳昌. 區(qū)塊鏈原理、設(shè)計(jì)與應(yīng)用[M]. 機(jī)械工業(yè)出版社, 2017.8
[3] 蔣勇. 白話區(qū)塊鏈[M]. 機(jī)械工業(yè)出版社, 2017.10
[4] Nakamoto S. Bitcoin. a peer-to-peer electronic cash system
https://bitcoin.org/bitcoin.pdf, 2009.1
[5] Diego Ongaro, John Ousterhout. In Search of Understandable Consensus Algorithm 2013
[6] 袁勇,王飛躍. 區(qū)塊鏈技術(shù)發(fā)展現(xiàn)狀與發(fā)展 2016.4文章來源:http://www.zghlxwxcb.cn/news/detail-705186.html
5、資源下載
本項(xiàng)目源碼及完整論文如下,有需要的朋友可以點(diǎn)擊進(jìn)行下載。如果鏈接失效可點(diǎn)擊下方卡片掃碼自助下載。文章來源地址http://www.zghlxwxcb.cn/news/detail-705186.html
序號 | 畢業(yè)設(shè)計(jì)全套資源(點(diǎn)擊下載) |
---|---|
本項(xiàng)目源碼 | 基于Raft+區(qū)塊鏈的共識算法Raft設(shè)計(jì)與實(shí)現(xiàn)(源碼+文檔)_Raft_共識算法Raft.zip |
到了這里,關(guān)于Raft畢業(yè)設(shè)計(jì)——基于Raft+區(qū)塊鏈的共識算法Raft設(shè)計(jì)與實(shí)現(xiàn)(畢業(yè)論文+程序源碼)——共識算法Raft的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!