何時需要進(jìn)行l(wèi)eader選舉
- zookeeper服務(wù)啟動時候
- zookeeper服務(wù)器服務(wù)期間,無法與leader進(jìn)行通信汗盘。
選舉過程中兼耀,要求倦踢,被選舉對象的支持票數(shù)必須在一半以上磁浇,方能生效斋陪,少數(shù)服從多數(shù)。
選票5個基本概念置吓,
- serverid鳍贾,sid,機(jī)器的server id交洗,在配置文件中
- zxid,ZooKeeper Transaction Id橡淑,64位長度构拳,由兩部分構(gòu)成 ,高32位是leader epoch梁棠,低32位是計數(shù)器
- leader epoch置森,32位表示,融合在zxid中符糊,每次選舉leader時候凫海,會加1,表明一個新的時代 要產(chǎn)生男娄。
- 計數(shù)器行贪,32位表示,融合在zxid中模闲,每次對數(shù)據(jù)的更改建瘫,一次請求,加1尸折,leader負(fù)責(zé)累加操作啰脚,影響后續(xù)的事物操作結(jié)果。
- logicalclock实夹,選舉時鐘周期橄浓,每個機(jī)器要進(jìn)行選舉了,就將自己的logicalclock加1
這里的zxid雖然包含了epoch亮航,那是leader確定后荸实,create或者update的數(shù)據(jù)節(jié)點(diǎn)加上時間戳,這個時間戳包含了當(dāng)前生效的epoch塞赂,也即當(dāng)前生效的logicalclock泪勒,直接忽略zxid中的epoch昼蛀,就理解zxid是事物id,嚴(yán)格遞增圆存,每個服務(wù)器節(jié)點(diǎn)叼旋,都能保存最新的自己的zxid。
投票券構(gòu)成(sid, zxid)沦辙,之外夫植,還包括當(dāng)前服務(wù)器狀態(tài),logicalclock,等信息。
服務(wù)器啟動過程中的leader選舉和運(yùn)行期間的leader選舉原理一致油讯,只是啟動過程中详民,服務(wù)器啟動有快有慢而已,選舉過程簡單陌兑,當(dāng)足夠的選票到達(dá)后能夠確定一個leader后沈跨,后續(xù)啟動的機(jī)器再溝通后,直接變成follower兔综。
選舉過程中機(jī)器的狀態(tài)
- Looking饿凛,尋找leader狀態(tài)
- following,跟隨狀態(tài)软驰,即涧窒,follower
- leading,領(lǐng)導(dǎo)者狀態(tài)锭亏,即纠吴,leader
- observing,觀察者狀態(tài)慧瘤,即戴已,observer
選舉通道
每臺服務(wù) 器在啟動的過程中,會啟動一個QuorumPeerManager锅减,負(fù)責(zé)各臺服務(wù)器之間的底層Leader選舉過程中的網(wǎng)絡(luò)通信
消息隊列
QuorumPeerManager維護(hù)一系列隊列和相應(yīng)的處理線程
- 一個接收隊列恭陡,接收其他服務(wù)器發(fā)來的消息,recvQueue上煤,
- 若干個接收器休玩,RecvWorker,集群中其他服務(wù)器劫狠,每個對應(yīng)一個RecvWorker拴疤,
- 若干個發(fā)送隊列,按照其他機(jī)器sid個數(shù)分組形成隊列集合独泞,queueSendMap
- 若干個發(fā)送器呐矾,按照其他機(jī)器sid個數(shù)分組形成發(fā)送器集合,senderWorkerMap
- 上一次發(fā)出去的投票信息懦砂,lastMessageSent蜒犯,為每個sid都保留一個上次的發(fā)送的投票
建立連接
為了能夠投票组橄,zookeeper集群中每兩臺機(jī)器之間都要建立通信,QuorumPeerManager會創(chuàng)建ServerSocket來監(jiān)聽端口(3888)罚随,接受Leader選舉過程中的通信信息玉工。
為避免兩臺機(jī)器之間重復(fù)建立TCP連接,Zookeeper只允許SID大的服務(wù)器主動和其他機(jī)器建立連接淘菩,否則斷開連接遵班。在接收到創(chuàng)建連接請求后,服務(wù)器通過對比自己和遠(yuǎn)程服務(wù)器的SID值來判斷是否接收連接請求潮改,如果當(dāng)前服務(wù)器發(fā)現(xiàn)自己的SID更大狭郑,那么會斷開當(dāng)前連接,然后自己主動和遠(yuǎn)程服務(wù)器建立連接汇在。一旦連接建立翰萨,就會根據(jù)遠(yuǎn)程服務(wù)器的SID來創(chuàng)建相應(yīng)的消息發(fā)送器SendWorker和消息接收器RecvWorker。
收發(fā)消息
在SendWorker中糕殉,一旦Zookeeper發(fā)現(xiàn)針對當(dāng)前服務(wù)器的消息發(fā)送隊列為空缨历,那么此時需要從lastMessageSent中取出一個最近發(fā)送過的消息來進(jìn)行再次發(fā)送,這是為了解決接收方在消息接收前或者接收到消息后服務(wù)器掛了糙麦,導(dǎo)致消息尚未被正確處理。
同時丛肮,Zookeeper能夠保證接收方在處理消息時赡磅,會對重復(fù)消息進(jìn)行正確的處理
接受消息
由消息接收器RecvWorker負(fù)責(zé),由于Zookeeper為每個遠(yuǎn)程服務(wù)器都分配一個單獨(dú)的RecvWorker宝与,因此焚廊,每個RecvWorker只需要不斷地從這個TCP連接中讀取消息,并將其保存到recvQueue隊列中
發(fā)送消息
由于Zookeeper為每個遠(yuǎn)程服務(wù)器都分配一個單獨(dú)的SendWorker习劫,因此咆瘟,每個SendWorker只需要不斷地從對應(yīng)的消息發(fā)送隊列中獲取出一個消息發(fā)送即可,同時將這個消息放入sid對應(yīng)的lastMessageSent中
FastLeaderElection選舉算法
在3.4.0后的Zookeeper的版本只保留了TCP版本的FastLeaderElection選舉算法诽里。
流程如下袒餐,
- 自增選舉輪次。Zookeeper規(guī)定所有有效的投票都必須在同一輪次中谤狡,在開始新一輪投票時灸眼,會首先對logicalclock進(jìn)行自增操作。
- 初始化選票墓懂。在開始進(jìn)行新一輪投票之前焰宣,每個服務(wù)器都會初始化自身的選票,并且在初始化階段捕仔,每臺服務(wù)器都會將自己推舉為Leader匕积。
- 發(fā)送初始化選票盈罐。完成選票的初始化后,服務(wù)器就會發(fā)起第一次投票闪唆。Zookeeper會將剛剛初始化好的選票放入sendqueue中盅粪,由發(fā)送器WorkerSender負(fù)責(zé)發(fā)送出去壶硅。
- 接收外部投票堪侯。每臺服務(wù)器會不斷地從recvqueue隊列中獲取外部選票。如果服務(wù)器發(fā)現(xiàn)無法獲取到任何外部投票踢关,那么就會立即確認(rèn)自己是否和集群中其他服務(wù)器保持著有效的連接笼吟,如果沒有連接库物,則馬上建立連接,如果已經(jīng)建立了連接贷帮,則再次發(fā)送自己當(dāng)前的內(nèi)部投票戚揭。
- 判斷選舉輪次。在發(fā)送完初始化選票之后撵枢,接著開始處理外部投票民晒。在處理外部投票時,會根據(jù)選舉輪次來進(jìn)行不同的處理锄禽。
- 外部投票的選舉輪次大于內(nèi)部投票潜必。若服務(wù)器自身的選舉輪次落后于該外部投票對應(yīng)服務(wù)器的選舉輪次,那么就會立即更新自己的選舉輪次(logicalclock)沃但,并且清空所有已經(jīng)收到的投票磁滚,然后使用初始化的投票來進(jìn)行PK以確定是否變更內(nèi)部投票。最終再將內(nèi)部投票發(fā)送出去宵晚。
- 外部投票的選舉輪次小于內(nèi)部投票垂攘。若服務(wù)器接收的外選票的選舉輪次落后于自身的選舉輪次,那么Zookeeper就會直接忽略該外部投票淤刃,不做任何處理晒他,并返回步驟4。
- 外部投票的選舉輪次等于內(nèi)部投票逸贾。此時可以開始進(jìn)行選票PK陨仅。
- 選票PK。在進(jìn)行選票PK時铝侵,符合任意一個條件就需要變更投票掂名。
- 若選舉輪次一致,那么就對比兩者的ZXID哟沫,若外部投票的ZXID大饺蔑,那么需要變更投票。
- 若兩者的ZXID一致嗜诀,那么就對比兩者的SID猾警,若外部投票的SID大孔祸,那么就需要變更投票。
- 變更投票发皿。經(jīng)過PK后崔慧,若確定了外部投票優(yōu)于內(nèi)部投票,那么就變更投票穴墅,即使用外部投票的選票信息來覆蓋內(nèi)部投票惶室,變更完成后,再次將這個變更后的內(nèi)部投票發(fā)送出去玄货。
- 選票歸檔皇钞。無論是否變更了投票,都會將剛剛收到的那份外部投票放入選票集合recvset中進(jìn)行歸檔松捉。recvset用于記錄當(dāng)前服務(wù)器在本輪次的Leader選舉中收到的所有外部投票(按照服務(wù)隊的SID區(qū)別夹界,如{(1, vote1), (2, vote2)...})。
- 統(tǒng)計投票隘世。完成選票歸檔后可柿,就可以開始統(tǒng)計投票,統(tǒng)計投票是為了統(tǒng)計集群中是否已經(jīng)有過半的服務(wù)器認(rèn)可了當(dāng)前的內(nèi)部投票丙者,如果確定已經(jīng)有過半服務(wù)器認(rèn)可了該投票复斥,則終止投票。否則返回步驟4械媒。
- 更新服務(wù)器狀態(tài)目锭。若已經(jīng)確定可以終止投票,那么就開始更新服務(wù)器狀態(tài)滥沫,服務(wù)器首選判斷當(dāng)前被過半服務(wù)器認(rèn)可的投票所對應(yīng)的Leader服務(wù)器是否是自己,若是自己键俱,則將自己的服務(wù)器狀態(tài)更新為LEADING兰绣,若不是,則根據(jù)具體情況來確定自己是FOLLOWING或是OBSERVING编振。
以上10個步驟就是FastLeaderElection的核心缀辩,其中步驟4-9會經(jīng)過幾輪循環(huán),直到有Leader選舉產(chǎn)生