如此火爆的ZooKeeper,到底如何选主?
? 前言?
前面一篇文章我們已經(jīng)給大家講解了ZooKeeper的核心的原理,這一篇我們重點分析ZooKeeper的Leader選舉算法。Leader的選舉是ZooKeeper的最重要技術之一,也是保證分布式系統(tǒng)數(shù)據(jù)一致的關鍵。
? Leader選舉流程概述?
我們本篇文章的目的就是詳細的剖析Leader選舉的過程,但是Leader選舉的過程較為復雜,我們直接上來就講其詳細的過程,大家容易蒙圈,所以我們這一小段就簡單描述一下Leader選舉的大概流程。
如上圖所以,假設我們目前有一個3個節(jié)點構(gòu)成的ZooKeeper集群,myid的編號分別是0,1,2,又因為集群當前是一個空的集群,所以每個節(jié)點的ZXID初始都為0,該集群啟動的時候Leader的選舉流程如下:
(1)我們首先啟動myid為0的服務,但是目前只有一臺ZooKeeper服務,所以是無法完成Leader選舉的,ZooKeeper集群要求Leader進行投票選舉條件是至少有2臺服務才行,不然都沒法進行通信投票。
(2)啟動myid為1的服務,第二臺啟動了以后,這兩臺ZooKeeper就可以相互通信了,接下來就可以進行投票選舉了。
(3)2臺ZooKeeper進行投票選舉的時候,第一次都是推薦自己為Leader,投票包含的信息是:服務器本身的myid和ZXID。比如第一臺投自己的話,它會發(fā)送給第二臺機器的投票是(0,0),第一個0代表的是機器的myid,第二個0代表是的ZXID。故兩臺機器收到的投票情況如下:
第一臺:(1,0)
第二臺:(0,0)
(4)兩臺服務器在接收到投票后,將別人的票和自己的投票進行PK。PK的是規(guī)則是:
?(a)優(yōu)先對比ZXID,ZXID大的優(yōu)先作為Leader(ZXID大的表示數(shù)據(jù)多)
?(b)如果ZXID一樣的話,那么就比較myid,讓myid大的作為Leader服務器。
那根據(jù)這個規(guī)則的話,第一臺服務器,接受到的投票是(1,0),跟自己的投票(0,0)比,ZXID是一樣的,但是myid比接收到的投票的小,所以第一臺原先是推薦自己投票為(0,0),現(xiàn)在進行了PK以后,投票修改為(1,0)。第二臺服務器,接受到的投票是(0,0),跟自己的投票(1,0)比,ZXID是一樣的,但是myid是比接受到的投票的大,所以堅持自己的投票(1,0)。兩臺服務器再次進行投票。
(5)每次投票以后,服務器都會統(tǒng)計所有的投票,只要過半的機器投了相同的機器,那么Leader就選舉成功了,上面的兩臺服務器進行第二次投票之后,兩臺服務器都會收到相同的投票(1,0)。那么此時myid為1的服務器就是Leader了。
如上的Leader選舉其實在集群啟動的過程中只需要幾毫秒就完成了,所以如果有搭建ZooKeeper集群經(jīng)驗的同學會發(fā)現(xiàn),我們?nèi)绻错樞騿臃盏脑?#xff0c;啟動到第二臺機器的時候,Leader就已經(jīng)選出來了,所以大家會看到一般第二臺就是Leader。第三臺啟動的時候就作為Follower。
上面我們描述的是集群在初始化過程中Leader的選舉流程,如果集群在運行的過程中Follower節(jié)點宕機了,對Leader節(jié)點是不影響的,如果集群在運行的過程中Leader節(jié)點宕機了,就會進行重新選舉,重新選舉的流程跟上述一致。
? Leader選舉的詳細流程?
如上圖是ZooKeeper選舉的核心算法邏輯圖,接下來我們詳細的看一下其選舉流程。
0x01 投票輪次遞增
用于標識當前投票的輪次,ZooKeeper規(guī)定了同一輪次的投票才是有效的。所以如果要進行新一輪的投票,需要對投票輪次進行遞增。
0x02 初始化選票
在投票之前每臺服務器都會初始化自己的選票,選票里面最重要的兩個值一個是本機的myid的值,一個是本機的ZXID的值。
0x03 發(fā)送初始化選票
完成選票的初始化以后,服務器就會發(fā)起第一次投票,第一次投票都是推薦自己為Leader,也就是都投自己。
0x04 判斷服務狀態(tài)
ZooKeeper的服務有四個狀態(tài):LOOKING, FOLLOWING, LEADING, OBSERVING
LOOKING:尋找Leader的狀態(tài)。
FOLLOWING:跟隨者狀態(tài)。
LEADING:領導者狀態(tài)。
OBSERVING:觀察者狀態(tài)。
如果當前服務的狀態(tài)是LOOKING,那么說明還沒選舉出來Leader,繼續(xù)下面的步驟,正常情況下一開始都是LOOKING的狀態(tài)。
0x05 接受外部選票
每臺服務器會不斷的從某個隊列里面獲取外部的選票。如果發(fā)現(xiàn)服務器無法獲取外部的任何選票,那么就會立即確認自己是否和集群中的其他服務器保持著有效連接。如果發(fā)現(xiàn)沒有建立連接,那么立馬建立連接。如果已經(jīng)建立連接了,那么再次發(fā)送自己的投票。
0x06 判斷選舉輪次
發(fā)送完初始化選票以后,接下來就要處理外部的選票了,處理選票的時候會根據(jù)不同輪次的選票進行不同的處理。
??6.1 外部投票的選舉輪次大于自己的輪次
如果發(fā)現(xiàn)自己的投票輪次小于外部的輪次,那么立即更新自己的輪次,然后清空已經(jīng)接收到的選票。然后使用初始化的選票來PK剛剛的外部投票以確定是否變更自己的投票(PK的規(guī)則跟概述里描述一致)。
??6.2 外部投票的選舉輪次小于自己的輪次
如果接收到的選票的選舉輪次落后與服務器本身的輪次,那么直接忽略該外部選票,不做任何處理。
??6.3 外部投票的選舉輪次等于自己的輪次
大多數(shù)屬于這個情況,如果外部的選票的輪次跟自己的選票輪次一致的話,就進行選票PK。
0x07 選票PK
(a)優(yōu)先對比ZXID,ZXID大的優(yōu)先作為Leader。
(b)如果ZXID一樣的話,那么就比較選票里的myid,myid大的選為Leader。
0x08 變更選票
通過選票PK以后,如果確定了別的服務的選票優(yōu)于自己的選票,那么就進行選票變更,把自己的選票信息變更為更適合作為Leader的服務器的選票信息。然后再把這些選票發(fā)送出去。不過無論是否發(fā)生了選票變更,當前的服務都會將剛剛接收到的選票進行歸檔并按照服務器的myid來區(qū)分,如:{(0,vote1),(1,vote2),....}
0x09 統(tǒng)計投票
完成了選票歸檔之后,就可以統(tǒng)計選票了,說白了就是看是否有過半的服務器認為某臺服務器適合做Leader,如果確定了則終止投票。否者返回步驟(4)。
0x0A 更新服務狀態(tài)
統(tǒng)計投票后,如果已經(jīng)確定出來Leader就終止投票,接下來就變更服務的狀態(tài),首先看一下自己是不是Leader,如果自己是Leader那么就更新自己的狀態(tài)為Leader,如果不是Leader,那么就根據(jù)配置文件,要么切換為Follower,要么切換為Observer。
以上10個步驟就是ZooKeeper選舉的核心算法,其中4-9會經(jīng)過幾輪循環(huán)直到Leader產(chǎn)生。
最后
ZooKeeper是我們學習架構(gòu)的過程中必不可少的一個技術,今天主要跟大家講解了ZooKeeper的Leader選舉算法,后面會陸續(xù)剖析ZooKeeper的ZAB協(xié)議算法,數(shù)據(jù)快照機制,數(shù)據(jù)清理機制,會話機制,長連接機制等。歡迎大家持續(xù)關注。
總結(jié)
以上是生活随笔為你收集整理的如此火爆的ZooKeeper,到底如何选主?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HashSet 和 LinkedHash
- 下一篇: 手把手教你实现一个 JSON 解析器!