Zab,Raft,Viewstamp的區別(1)選舉;

首先,這幾個協議都是用來實現數據一致性的,都使用了quorum來達成共識,並且都使用了leader-follower的形成來進行數據同步

它們究竟有啥區別,本文主要說說 選舉方面的區別。首先看raft

1、Raft選舉涉及的幾個概念

(1)raft的每一個伺服器(server)都處於三個狀態之一:leader,follower,candidate。

(2)term:raft將時間分成各個時隙,每個term內有唯一的leader,遞增

(3)log index:raft中每個log都有唯一的index

2、Raft的選舉期望

Raft要求選舉出來的leader包含了所有已經提交的log entry。

(1)、正常狀態下leader 發送心跳到follower,若follower超時未收到來自leader的心跳,則follower發起election。

(2)、發起election的follower切換狀態到candidate並給自己投票,該伺服器保持此狀態直到如下三個事件發生。

a.贏得選舉

b.其他伺服器贏得選舉

c.超時沒有人贏選舉

(3)、某一candidate在同一個term獲得大多數server投票,贏得選舉,變成leader,發送心跳到其他伺服器

(4)、在選舉過程中,伺服器A可能收到其他伺服器B當選請求,若B的vote相較於A的vote「更新」,則認為該選舉合法,A切換回follower,否則拒絕該請求。

附 「更新」 定義:

若參與比較的兩個server中current term不同,則term更大的更新,否則log index更大的更新

4、Raft投票原則

當一個candidate發起選舉時,其他server使用on afirst-come-first-served basis原則,若在一定時間內,沒選出來主(即沒有達成quorum),則重啟選舉。

我們再來看看Zab協議

Zab本身沒有規定選舉演算法,只要求達到quorum就好,但是Zab有個預設FLE(FastleaderElection)演算法,下文Zab的選舉流程即指代FLE演算法

1、Zab中的幾個基本概念

(1)和Raft類似,Zab的伺服器(Zab論文中使用peer,其實和Raft的server是一回事)也有三個狀態:election、following、leading。其中election對應Raft的candidate、following對應Raft的follower,leading和Raft的leader略有差別,下文會詳述。

(2)Zxid: 在zab中,一個事務被Zxid唯一標識,Zxid是一個二元組(e,c),其中e是事務的epoch編號,c是counter

(3)round:選舉投票的輪次

(4)對p(i)的一個vote的:一個vote可表示為(z(i),i),其中z(i)是p(i)的最後一個事務。兩個vote(z(i),i)大於(z(j),j)時滿足,z(i)>z(j)或【z(i)=z(j),且i>=j】

2、Zab的選舉期望

Zab本身不對選舉有任何期望要求,任意一個peer都可以做primary,只需收到quorum的投票就好。但zab預設的FLE演算法同樣要求選出來的,要求選舉出來的primary包含了最新propose的log(可以沒有commit),下文講的流程也是FLE的流程。

3、Zab的選舉流程

(1)peer在啟動階段,處於election狀態,正常情況下,primary收到心跳到其它peer,若超時未收到quorum的心跳,則primary切狀態至election,發起選舉。同樣 follower若超時也發起選舉。選舉時peer首先投票給自己,投票輪次+1,發送notification(vote,id,state,round),其中vote是其意向leader(初始是自己),id是自己的id,state為election,round是輪次

(2)一旦peer P收到來自peer Q的notification,若P自身狀態是election,將Q的投票壓入P的FIFO隊列,若Q的狀態是election且P自身的round大於Q的round,說明P是一個更新的投票,則P發送P自身選舉信息給Q。(P投票的peer id P自身id P狀態 P輪次),若P的狀態不是election(following或者leading,此時意味著已有quorum達成共識),則P發送自己選舉信息給Q。

(3)P(只是符號,不一定是上面的P)檢查自己的隊列,若隊列為空,則發送自己選舉信息到其餘peer。否則,若第一個收到的選舉信息的來自peer Q,且Q為election(說明系統剛啟動或者leader故障,大家都是election)。此時分三種情況,

a. Q輪次比P更新。更新P投票輪次為Q的輪次,清空P收到的投票。若此時Q.vote相對於(P.lastZxid,P.id)較大,P使用Q投票的peer作為自己投票的peer),否則P繼續投票給自己(P.vote=(P.lastZxid,P.id))。

b. Q和P輪次相等 , 若此時Q.vote相對於(P.lastZxid,P.id)較大,P使用Q投票的peer作為自己投票的peer),發送投票信息

c.Q.輪次小 ,則取P隊列中收到的下個投票信息

(4)記錄投票,若記錄中有一個quorum並且在時間閾值能沒有收到其他投票信息或P收到的投票數量為全體伺服器投票。此時根據P的投票,若P投自己,則置狀態為leading,否則置狀態為follower。

以上部分是系統啟動或leader故障時狀態,以下為P是新加入系統 系統有leader

(5)此時Q為leading或following

若Q.round=P.round,記錄Q的投票,此時有三種情況

a.若Q為leading 則結束P切為follower

b.若Q投P且構成quorum 則P為leading

c.若Q投其它 並且構成quorum 且在有已經存在的成功投票 則P為follower Q投票對象為主投票結束

記錄Q為已經成功投票

a. Q投p 則p為leading結束

b. Q是一個成功的投票 使用Q的投票做leading, 結束。

關於zab的選舉可以看看這篇文章

圖解zookeeper FastLeader選舉演算法。

VR沒有具體的選舉演算法,VR的primary是通過配置和當前primary計算得到下一個primary,具體的流程如下可以參考論文。

這裡主要對比Raft和Zab下區別

1、log的連續性和消息流向

Raft的log(Paxos不要求log連續,Raft本質上是Paxos的特殊情況)必需連續,選出來的leader擁有最多的log,消息流向必須是leader到follower。Zab本身不要求log連續,可以由follower同步到leader。FLE演算法log也必須連續,follower根據leader的log內容更新自己log。

2、leader的確定時間

Raft在達成quorum時已經確定leader,leader開始工作接受請求並廣播。由leader向follower同步消息,可能會出現下圖

(a)在term2 S1是leader,將數據2同步至S2,S1 crash

(b)此時由於數據2未達成quorum,S5在term2 當選為leader S5寫數據3 然後crash

(c)S1重啟,將數據2同步至S3,達成quorum,然後進入term3 寫數據4,crash

(d)因為在term3,沒有達成quorum,並且S2,S3,S4,S5的最後一個log id一致,S5可能當選,此時,S5使用數據3 同步到term2,覆蓋已經提交的數據2

(e)若S1在crash之前將數據4同步至quorum,則S5不能再term3贏得選舉

為了避免上述情況(d)發生,Raft要求在當前term的時候不能直接提交之前term信息。只有在提交本term數據的時候,順帶提交之前term的數據。由於選舉時的要求leader包含所有已經commit的日誌,在當前term時,primary進行數據達到quorum提交的時候,之前term的數據必然也達到了quorum。也就是說,在上圖的情況下,當前term3數據提交的時候,S5是不可能當選為leader的。

Zab在達成quorum時選出「leader」,然後這裡的「leader」只是一個候選,「leader」並不將請求廣播,需要首先進行「leader」和follower的數據同步,達成同步後,建立連接,「leader」才真正成為leader開始廣播新請求。Zab從根本上避免了上述問題。

3、選舉的觸發

Raft:目前只是follower在檢測。follower有一個選舉時間,在該時間內如果未收到leader的心跳信息,則follower轉變成candidate,自增term發起新一輪的投票,leader遇到新的term則自動轉變成follower的狀態

ZooKeeper:leader和follower都有各自的檢測超時方式,leader是檢測是否過半follower心跳回復了,follower檢測leader是否發送心跳了。一旦leader檢測失敗,則leader進入election狀態,其他follower過一段時間因收不到leader心跳也會進入election狀態,從而出發新的leader選舉。一旦follower檢測失敗了,則該follower進入election狀態,此時leader和其他follower仍然保持良好,則該follower仍然是去學習上述leader的投票,而不是觸發新一輪的leader選舉。

4、投票的輪次

Raft使用一輪投票,並採用「哪個candidate先請求投票誰就可能先獲得投票」的策略,可能造成投票衝突即各個candidate都沒有收到過半的投票,此時raft重啟投票。

ZooKeeper中的每個server,ZooKeeper中的每個server,在某個electionEpoch輪次內,可以投多次票,只要遇到更大的票就更新,然後分發新的投票給所有人。這種情況下不存在split vote現象,同時有利於選出含有更新更多的日誌的server,但是選舉時間理論上相對Raft要花費的多。並且理論上可能出現活鎖問題。

5、之前leader的干擾

Raft的copycat實現為:每個follower開通一個複製數據的RPC介面,誰都可以連接並調用該介面,所以Raft需要來阻止上一輪次的leader的調用。每一輪次都會有對應的輪次號,用來進行區分,Raft的輪次號就是term,一旦舊leader對follower發送請求,follower會發現當前請求term小於自己的term,則直接忽略掉該請求,自然就解決了舊leader的干擾問題

ZooKeeper:一旦server進入leader選舉狀態則該follower會關閉與leader之間的連接,所以舊leader就無法發送複製數據的請求到新的follower了,也就無法造成干擾了

參考

Raft對比ZAB協議 - zzm - ITeye技術網站

圖解zookeeper FastLeader選舉演算法。

tcs.hut.fi/Studies/T-79

pdos.csail.mit.edu/6.82

scs.stanford.edu/14au-c

推薦閱讀:

raft協議應用方面的疑問?
etcd-raft節點變更
事件和時間:Time, Clocks, and the Ordering of Events in a Distributed System 讀後感
一致性, 兩階段提交和事務提交的發展史(譯)
raft 經典場景分析

TAG:分布式一致性 | ZooKeeper | 分布式系统 |