圖解zookeeper FastLeader選舉算法

zookeeper當配置爲羣集模式,在啓動或異常狀況將被選舉爲的例子Leader。默認選擇算法FastLeaderElectionjava

不知道zookeeper夠考慮這樣一個問題:某個服務可以配置爲多個實例共同構成一個集羣對外提供服務。其每一個實例本地都存有冗餘數據,每一個實例都可以直接對外提供讀寫服務。在這個集羣中爲了保證數據的一致性,需要有一個Leader來協調一些事務。那麼問題來了:怎樣肯定哪個實例是Leader呢?算法

問題的難點在於:分佈式

  • 沒有一個仲裁者來選定Leader
  • 每一個實例本地可能已經存在數據,不肯定哪一個實例上的數據是最新的

分佈式選舉算法正是用來解決問題的。post

本文基於zookeeper 3.4.6 的源代碼進行分析。FastLeaderElection算法的源代碼全部位於FastLeaderElection.java文件裏,其對外接口爲FastLeaderElection.lookForLeader,該接口是一個同步接口,直到選舉結束纔會返回。相同由於網上已有相似文章,因此我就從圖示的角度來闡述。閱讀一些其它文章有利於得到初步印象:.net

主要流程

閱讀代碼和以上推薦文章可以把整個流程梳理清楚。線程

實現上,包含了一個消息處理主循環,也是選舉的主要邏輯。以及一個消息發送隊列處理線程和消息解碼線程。主要流程可歸納爲下圖:code

fle-flow.png

推薦對比着推薦的文章及代碼理解。不贅述。blog

咱們從感性上來理解這個算法。接口

每一個節點,至關於一個選民,他們都有本身的推薦人,最開始他們都推薦本身。隊列

誰更適合成爲Leader有一個簡單的規則,好比sid夠大(配置)、持有的數據夠新(zxid夠大)。

每一個選民都告訴其它選民本身眼下的推薦人是誰。相似於出去搞宣傳拉攏其它選民。每一個選民發現有比本身更適合的人時就轉而推薦這個更適合的人。最後。大部分人意見一致時,就可以結束選舉。

就這麼簡單。

總體上有一種不斷演化逼近結果的感受。

固然。會有些特殊狀況的處理。

好比總共3個選民,1和2已經肯定3是Leader,但3還不知情,此時就走入LEADING/FOLLOWING的分支,選民3僅僅是接收結果。

代碼中不是所有邏輯都在這個大流程中完畢的。

在接收消息線程中。還可能單獨地迴應某個節點(WorkerReceiver.run):

recv.png

從這裏可以看出。當某個節點已經肯定選舉結果再也不處於LOOKING狀態時。其收到LOOKING消息時都會直接回應選舉的終於結果。結合上面那個例如。至關於某次選舉結束了,這個時候來了選民4又發起一次新的選舉,那麼其它選民就直接告訴它當前的Leader狀況。至關於,在這個集羣主從已經就緒的狀況下,又開啓了一個實例,這個實例就會直接使用當前的選舉結果。

狀態轉換

每個節點上有一些重要的做用結構:

  • 當前推薦人。初始推薦本身。每次收到其它更好的推薦人時就更新
  • 其它人的投票集合。用於肯定什麼時候選舉結束

每次推薦人更新時就會進行廣播,正是這個不斷地廣播驅動整個算法趨向於結果。

若是有3個節點A/B/C,其都尚未數據,依照sid關係爲C>B>A,那麼依照規則。C更可能成爲Leader,其各個節點的狀態轉換爲:

state.png

圖中。v(A)表示當前推薦人爲A。r[]表示收到的投票集合。

可以看看當其它節點已經肯定投票結果時,即再也不是LOOKING時的狀態:

state-ret.png

代碼中有一個特殊的投票集合outofelection,我理解爲選舉已結束的那些投票,這些投票僅用於表徵選舉結果。

當一個新啓動的節點增長集羣時。它對集羣內其它節點發出投票請求。而其它節點已不處於LOOKING狀態,此時其它節點回應選舉結果。該節點收集這些結果到outofelection中,終於在收到合法LEADER消息且這些選票也構成選舉結束條件時,該節點就結束本身的選舉行爲。注意到代碼中會logicalclock = n.electionEpoch;更新選舉輪數

相關文章
相關標籤/搜索