術(shù)語介紹
myid
每個Zookeeper服務(wù)器睦授,都需要在數(shù)據(jù)文件夾下創(chuàng)建一個名為myid的文件剃允,該文件包含整個Zookeeper集群唯一的ID(整數(shù))省核。例如某Zookeeper集群包含三臺服務(wù)器结笨,hostname分別為zoo1签夭、zoo2和zoo3昌渤,其myid分別為1稻励、2和3,則在配置文件中其ID與hostname必須一一對應(yīng),如下所示望抽。在該配置文件中加矛,server.
后面的數(shù)據(jù)即為myid
server.1=zoo1:2888:3888
server.2=zoo2:2888:3888
server.3=zoo3:2888:3888
zxid
類似于RDBMS中的事務(wù)ID,用于標(biāo)識一次更新操作的Proposal ID煤篙。為了保證順序性斟览,該zkid必須單調(diào)遞增。因此Zookeeper使用一個64位的數(shù)來表示辑奈,高32位是Leader的epoch苛茂,從1開始,每次選出新的Leader鸠窗,epoch加一妓羊。低32位為該epoch內(nèi)的序號,每次epoch變化稍计,都將低32位的序號重置畅卓。這樣保證了zkid的全局遞增性缨恒。
支持的領(lǐng)導(dǎo)選舉算法
可通過electionAlg
配置項設(shè)置Zookeeper用于領(lǐng)導(dǎo)選舉的算法椎扬。
到3.4.10版本為止尺迂,可選項有
-
0
基于UDP的LeaderElection -
1
基于UDP的FastLeaderElection -
2
基于UDP和認(rèn)證的FastLeaderElection -
3
基于TCP的FastLeaderElection
在3.4.10版本中,默認(rèn)值為3硅则,也即基于TCP的FastLeaderElection淹父。另外三種算法已經(jīng)被棄用,并且有計劃在之后的版本中將它們徹底刪除而不再支持怎虫。
FastLeaderElection
FastLeaderElection選舉算法是標(biāo)準(zhǔn)的Fast Paxos算法實現(xiàn)暑认,可解決LeaderElection選舉算法收斂速度慢的問題。
服務(wù)器狀態(tài)
- LOOKING 不確定Leader狀態(tài)大审。該狀態(tài)下的服務(wù)器認(rèn)為當(dāng)前集群中沒有Leader穷吮,會發(fā)起Leader選舉
- FOLLOWING 跟隨者狀態(tài)。表明當(dāng)前服務(wù)器角色是Follower饥努,并且它知道Leader是誰
- LEADING 領(lǐng)導(dǎo)者狀態(tài)捡鱼。表明當(dāng)前服務(wù)器角色是Leader,它會維護(hù)與Follower間的心跳
- OBSERVING 觀察者狀態(tài)酷愧。表明當(dāng)前服務(wù)器角色是Observer驾诈,與Folower唯一的不同在于不參與選舉,也不參與集群寫操作時的投票
選票數(shù)據(jù)結(jié)構(gòu)
每個服務(wù)器在進(jìn)行領(lǐng)導(dǎo)選舉時溶浴,會發(fā)送如下關(guān)鍵信息
- logicClock 每個服務(wù)器會維護(hù)一個自增的整數(shù)乍迄,名為logicClock,它表示這是該服務(wù)器發(fā)起的第多少輪投票
- state 當(dāng)前服務(wù)器的狀態(tài)
- self_id 當(dāng)前服務(wù)器的myid
- self_zxid 當(dāng)前服務(wù)器上所保存的數(shù)據(jù)的最大zxid
- vote_id 被推舉的服務(wù)器的myid
- vote_zxid 被推舉的服務(wù)器上所保存的數(shù)據(jù)的最大zxid
投票流程
自增選舉輪次
Zookeeper規(guī)定所有有效的投票都必須在同一輪次中士败。每個服務(wù)器在開始新一輪投票時闯两,會先對自己維護(hù)的logicClock進(jìn)行自增操作褥伴。
初始化選票
每個服務(wù)器在廣播自己的選票前,會將自己的投票箱清空漾狼。該投票箱記錄了所收到的選票重慢。例:服務(wù)器2投票給服務(wù)器3,服務(wù)器3投票給服務(wù)器1逊躁,則服務(wù)器1的投票箱為(2, 3), (3, 1), (1, 1)似踱。票箱中只會記錄每一投票者的最后一票,如投票者更新自己的選票稽煤,則其它服務(wù)器收到該新選票后會在自己票箱中更新該服務(wù)器的選票核芽。
發(fā)送初始化選票
每個服務(wù)器最開始都是通過廣播把票投給自己。
接收外部投票
服務(wù)器會嘗試從其它服務(wù)器獲取投票酵熙,并記入自己的投票箱內(nèi)轧简。如果無法獲取任何外部投票,則會確認(rèn)自己是否與集群中其它服務(wù)器保持著有效連接匾二。如果是哮独,則再次發(fā)送自己的投票;如果否假勿,則馬上與之建立連接。
判斷選舉輪次
收到外部投票后态鳖,首先會根據(jù)投票信息中所包含的logicClock來進(jìn)行不同處理
- 外部投票的logicClock大于自己的logicClock转培。說明該服務(wù)器的選舉輪次落后于其它服務(wù)器的選舉輪次,立即清空自己的投票箱并將自己的logicClock更新為收到的logicClock浆竭,然后再對比自己之前的投票與收到的投票以確定是否需要變更自己的投票浸须,最終再次將自己的投票廣播出去。
- 外部投票的logicClock小于自己的logicClock邦泄。當(dāng)前服務(wù)器直接忽略該投票删窒,繼續(xù)處理下一個投票。
- 外部投票的logickClock與自己的相等顺囊。當(dāng)時進(jìn)行選票PK肌索。
選票PK
選票PK是基于(self_id, self_zxid)與(vote_id, vote_zxid)的對比
- 外部投票的logicClock大于自己的logicClock,則將自己的logicClock及自己的選票的logicClock變更為收到的logicClock
- 若logicClock一致特碳,則對比二者的vote_zxid诚亚,若外部投票的vote_zxid比較大,則將自己的票中的vote_zxid與vote_myid更新為收到的票中的vote_zxid與vote_myid并廣播出去午乓,另外將收到的票及自己更新后的票放入自己的票箱站宗。如果票箱內(nèi)已存在(self_myid, self_zxid)相同的選票,則直接覆蓋
- 若二者vote_zxid一致益愈,則比較二者的vote_myid梢灭,若外部投票的vote_myid比較大,則將自己的票中的vote_myid更新為收到的票中的vote_myid并廣播出去,另外將收到的票及自己更新后的票放入自己的票箱
統(tǒng)計選票
如果已經(jīng)確定有過半服務(wù)器認(rèn)可了自己的投票(可能是更新后的投票)敏释,則終止投票库快。否則繼續(xù)接收其它服務(wù)器的投票。
更新服務(wù)器狀態(tài)
投票終止后颂暇,服務(wù)器開始更新自身狀態(tài)缺谴。若過半的票投給了自己,則將自己的服務(wù)器狀態(tài)更新為LEADING耳鸯,否則將自己的狀態(tài)更新為FOLLOWING