FastLeader選主算法:
看網上關於 zookeeper選主節點fast算法的描述,雖然有幾篇寫的非常不錯,但是總感覺描述的差一些,因此打算寫一個我認為的較為詳細的版本讓大家提點意見。當然如果有Paxos基礎那自然看起來非常很簡單。
具體的FAST算法流程如下所示:
下面詳細解釋一下這個流程:
首先給出幾個名詞定義:
(1)Serverid:在配置server時,給定的服務器的標示id。
(2)Zxid:服務器在運行時產生的數據id,zxid越大,表示數據越新。
(3)Epoch:選舉的輪數,即邏輯時鍾。隨着選舉的輪數++
(4)Server狀態:LOOKING,FOLLOWING,OBSERVING,LEADING
步驟:
一、 Server剛啟動(宕機恢復或者剛啟動)准備加入集群,此時讀取自身的zxid等信息。
二、 所有Server加入集群時都會推薦自己為leader,然后將(leader id 、 zixd 、 epoch)作為廣播信息,廣播到集群中所有的服務器(Server)。然后等待集群中的服務器返回信息。
三、 收到集群中其他服務器返回的信息,此時要分為兩類:該服務器處於looking狀態,或者其他狀態。
(1) 服務器處於looking狀態
首先判斷邏輯時鍾 Epoch:
a) 如果接收到Epoch大於自己目前的邏輯時鍾(說明自己所保存的邏輯時鍾落伍了)。更新本機邏輯時鍾Epoch,同時 Clear其他服務發送來的選舉數據(這些數據已經OUT了)。然后判斷是否需要更新當前自己的選舉情況(一開始選擇的leader id 是自己)
判斷規則rules judging:保存的zxid最大值和leader Serverid來進行判斷的。先看數據zxid,數據zxid大者勝出;其次再判斷leaderServerid, leader Serverid大者勝出;然后再將自身最新的選舉結果(也就是上面提到的三種數據(leader Serverid,Zxid,Epoch)廣播給其他server)
b) 如果接收到的Epoch小於目前的邏輯時鍾。說明對方處於一個比較OUT的選舉輪數,這時只需要將自己的 (leader Serverid,Zxid,Epoch)發送給他即可。
c) 如果接收到的Epoch等於目前的邏輯時鍾。再根據a)中的判斷規則,將自身的最新選舉結果廣播給其他 server。
同時Server還要處理2種情況:
a) 如果Server接收到了其他所有服務器的選舉信息,那么則根據這些選舉信息確定自己的狀態(Following,Leading),結束Looking,退出選舉。
b) 即使沒有收到所有服務器的選舉信息,也可以判斷一下根據以上過程之后最新的選舉leader是不是得到了超過半數以上服務器的支持,如果是則嘗試接受最新數據,倘若沒有最新的數據到來,說明大家都已經默認了這個結果,同樣也設置角色退出選舉過程。
(2) 服務器處於其他狀態(Following, Leading)
a) 如果邏輯時鍾Epoch相同,將該數據保存到recvset,如果所接收服務器宣稱自己是leader,那么將判斷是不是有半數以上的服務器選舉它,如果是則設置選舉狀態退出選舉過程
b) 否則這是一條與當前邏輯時鍾不符合的消息,那么說明在另一個選舉過程中已經有了選舉結果,於是將該選舉結果加入到outofelection集合中,再根據outofelection來判斷是否可以結束選舉,如果可以也是保存邏輯時鍾,設置選舉狀態,退出選舉過程。
以上就是FAST選舉過程。
Zookeeper具體的啟動日志如下圖所示:
以上就是我自己配置的Zookeeper選主日志,從一開始LOOKING,然后new election, my id = 1, proposedzxid=0x0 也就是選自己為Leader,之后廣播選舉並重復之前Fast選主算法,最終確定Leader。