Consensus algorithms allow a collection of machines to work as a coherent group that can survive the failures of some of its members.算法
- 私鏈:傳統分佈式系統裏的共識算法(相較於區塊鏈這個概念),好比 zookeeper 的 zab 協議,paxos, raft。私鏈是不考慮集羣中存在做惡節點,只考慮由於系統或者網絡緣由致使的故障節點。
- 聯盟鏈:須要考慮集羣中存在故障節點,還須要考慮集羣中存在做惡節點。對於聯盟鏈,每一個新加入的節點都是須要驗證和審覈的。好比 pbft 算法
- 公鏈:須要考慮網絡中存在故障節點,還須要考慮做惡節點,這一點和聯盟鏈是相似的。和聯盟鏈最大的區別就是,公鏈中的節點能夠很自由的加入或者退出,不須要嚴格的驗證和審覈。好比pow.pos,dpos,ripple
- paxos是一類協議的統稱
- basic paxos
- multi-paxos 強化了leader
- raft 會有點像multi-paxos
兩個paper安全
- 小論文《In Search of an Understandable Consensus Algorithm》
- 大論文[《CONSENSUS: BRIDGING THEORY AND PRACTICE》]
一些實現的開源項目,etcd, tidb/tikv, consulbash
Raft算法由leader節點來處理一致性問題。leader節點接收來自客戶端的請求日誌數據,而後同步到集羣中其它節點進行復制,當日志已經同步到超過半數以上節點的時候,leader節點再通知集羣中其它節點哪些日誌已經被複製成功,能夠提交到raft狀態機中執行。app
經過以上方式,Raft算法將要解決的一致性問題分爲了如下幾個子問題。分佈式
節點剛啓動,進入follower狀態,同時建立一個超時時間在150-300毫秒之間的選舉超時定時器。
follower狀態節點主循環:
若是收到leader節點心跳:
心跳標誌位置1
若是選舉超時到期:
沒有收到leader節點心跳:
任期號term+1,換到candidate狀態。
若是收到leader節點心跳:
心跳標誌位置空
若是收到選舉消息:
若是當前沒有給任何節點投票過 或者 消息的任期號大於當前任期號:
投票給該節點
不然:
拒絕投票給該節點
candidate狀態節點主循環:
向集羣中其餘節點發送RequestVote請求,請求中帶上當前任期號term
收到AppendEntries消息:
若是該消息的任期號 >= 本節點任期號term:
說明已經有leader,切換到follower狀態
不然:
拒絕該消息
收到其餘節點應答RequestVote消息:
若是數量超過集羣半數以上,切換到leader狀態
若是選舉超時到期:
term+1,進行下一次的選舉
複製代碼
發起選舉時,follower將遞增它的任期號而後切換到candidate狀態。而後經過向集羣中其它節點發送RequestVote RPC請求來發起一次新的選舉。一個節點將保持在該任期內的candidate狀態下,直到如下狀況之一發生。區塊鏈
該candidate節點贏得選舉,即收到超過半數以上集羣中其它節點的投票。 另外一個節點成爲了leader。 選舉超時到來時沒有任何一個節點成爲leader。spa
日誌複製的流程大致以下:
每一個客戶端的請求都會被重定向發送給leader,這些請求最後都會被輸入到raft算法狀態機中去執行。
leader在收到這些請求以後,會首先在本身的日誌中添加一條新的日誌條目。
在本地添加完日誌以後,leader將向集羣中其餘節點發送AppendEntries RPC請求同步這個日誌條目,當這個日誌條目被成功複製以後(什麼是成功複製,下面會談到),leader節點將會將這條日誌輸入到raft狀態機中,而後應答客戶端。
committedIndex >= appliedIndex
複製代碼
Raft算法保持着如下兩個屬性,這兩個屬性共同做用知足前面提到的日誌匹配(LogMatch)屬性:日誌
- 領導人徹底原則:若是一個日誌條目在一個給定任期內被提交,那麼這個條目必定會出如今全部任期號更大的領導人中
- broadcastTime << electionTimeout << MTBF