簡述Zoookeeper集羣

1、Zookeeper集羣架構簡述:

Zookeeper可搭建服務器集羣,其架構如下:

Zookeeper集羣最好是單數,最好大於3臺,後續會說明原因,Zookeeper集羣有以下特性:

1、主從模式的集羣,它沒有做到數據分片(集羣中各節點數據一樣);
2、只有主能讀寫,從只能讀,寫請求發到從,從會把請求轉交給主(類似於Redis集羣);
3、自動選主(當集羣中一臺或部分宕機);
在學習之前先簡單介紹集羣的搭建。

2、Zookeeper集羣的搭建:

本例搭建的是僞集羣模式,即一臺機器上啓動三個Zookeeper實例組成集羣,真正的集羣模式無非就是實例IP地址不同,搭建方法沒有區別

Step1:配置JAVA環境,檢驗環境:java -version

Step2:下載並解壓zookeeper

cd /usr/local

wget http://mirror.bit.edu.cn/apache/zookeeper/stable/zookeeper-3.4.12.tar.gz

tar -zxvf zookeeper-3.4.12.tar.gz

cd zookeeper-3.4.12

Step3:重命名 zoo_sample.cfg文件

cp conf/zoo_sample.cfg conf/zoo-1.cfg

Step4:修改配置文件zoo-1.cfg,原配置文件裏有的,修改成下面的值,沒有的則加上

vim conf/zoo-1.cfg

dataDir=/tmp/zookeeper-1

clientPort=2181

server.1=127.0.0.1:2888:3888

server.2=127.0.0.1:2889:3889

server.3=127.0.0.1:2890:3890

配置說明
•    tickTime:這個時間是作爲 Zookeeper 服務器之間或客戶端與服務器之間維持心跳的時間間隔,也就是每個 tickTime 時間就會發送一個心跳。
•    initLimit:這個配置項是用來配置 Zookeeper 接受客戶端(這裏所說的客戶端不是用戶連接 Zookeeper 服務器的客戶端,而是 Zookeeper 服務器集羣中連接到 Leader 的 Follower 服務器)初始化連接時最長能忍受多少個心跳時間間隔數。當已經超過 10個心跳的時間(也就是 tickTime)長度後 Zookeeper 服務器還沒有收到客戶端的返回信息,那麼表明這個客戶端連接失敗。總的時間長度就是 10*2000=20 秒
•    syncLimit:這個配置項標識 Leader 與 Follower 之間發送消息,請求和應答時間長度,最長不能超過多少個 tickTime 的時間長度,總的時間長度就是 5*2000=10秒
•    dataDir:顧名思義就是 Zookeeper 保存數據的目錄,默認情況下,Zookeeper 將寫數據的日誌文件也保存在這個目錄裏。
•    clientPort:這個端口就是客戶端連接 Zookeeper 服務器的端口,Zookeeper 會監聽這個端口,接受客戶端的訪問請求。
•    server.A=B:C:D:其中 A 是一個數字,表示這個是第幾號服務器;B 是這個服務器的 ip 地址;C 表示的是這個服務器與集羣中的 Leader 服務器交換信息的端口;D 表示的是萬一集羣中的 Leader 服務器掛了,需要一個端口來重新進行選舉,選出一個新的 Leader,而這個端口就是用來執行選舉時服務器相互通信的端口。如果是僞集羣的配置方式,由於 B 都是一樣,所以不同的 Zookeeper 實例通信端口號不能一樣,所以要給它們分配不同的端口號。

Step4:再從zoo-1.cfg複製兩個配置文件zoo-2.cfgzoo-3.cfg,只需修改dataDirclientPort不同即可

cp conf/zoo-1.cfg conf/zoo-2.cfg

cp conf/zoo-1.cfg conf/zoo-3.cfg

vim conf/zoo-2.cfg

dataDir=/tmp/zookeeper-2

clientPort=2182

vim conf/zoo-2.cfg

dataDir=/tmp/zookeeper-3

clientPort=2183

Step5:標識Server ID

創建三個文件夾/tmp/zookeeper-1/tmp/zookeeper-2/tmp/zookeeper-2,在每個目錄中創建文件myid 文件,寫入當前實例的server id,即1.2.3

cd /tmp/zookeeper-1
vim myid
1
cd /tmp/zookeeper-2
vim myid
2
cd /tmp/zookeeper-3
vim myid
3

Step6:啓動三個zookeeper實例

bin/zkServer.sh start conf/zoo-1.cfg

bin/zkServer.sh start conf/zoo-2.cfg

bin/zkServer.sh start conf/zoo-3.cfg

Step7:檢測集羣狀態,也可以直接用命令“zkCli.sh -server IP:PORT”連接zookeeper服務端檢測

安裝好了,接下來我們一起來學習集羣的ZAB協議。

3、Zookeeper的原子廣播協議(ZAB):

ZAB 協議是爲分佈式協調服務ZooKeeper專門設計的一種支持崩潰恢復的一致性協議。基於該協議,ZooKeeper 實現了一種主從模式的系統架構來保持集羣中各個副本之間的數據一致性。ZAB協議運行過程中,所有的客戶端更新都發往Leader,Leader寫入本地日誌後再複製到所有的Follower節點。一旦Leader節點故障無法工作,ZAB協議能夠自動從Follower節點中重新選擇出一個合適的替代者,這個過程被稱爲選主,選主也是ZAB協議中最爲重要和複雜的過程。接下來介紹ZAB協議的選主過程以及在Zookeeper中的實現。

1、選主時機:

1、節點啓動時:

集羣啓動時,會選主。

2、節點異常:

Leader節點異常,會重新選主。

2、選主過程:

在描述詳細的選主過程之前,有必要交代一些概念,以便對接下來的大段文字不會有丈二和尚的感覺。

1、election epoch:

這是分佈式系統中極其重要的概念,由於分佈式系統的特點,無法使用精準的時鐘來維護事件的先後順序,因此,Lampert提出的Logical Clock就成爲了界定事件順序的最主要方式。

分佈式系統中以消息標記事件,所謂的Logical Clock就是爲每個消息加上一個邏輯的時間戳。在ZAB協議中,每個消息都被賦予了一個zxid,zxid全局唯一。zxid有兩部分組成:高32位是epoch,低32位是epoch內的自增id,由0開始。每次選出新的Leader,epoch會遞增,同時zxid的低32位清0。這其實像極了咱們古代封建王朝的君主更替,每一次的江山易主,君王更替。

2、zxid:

每個消息的編號,在分佈式系統中,事件以消息來表示,事件發生的順序以消息的編號來標記。在ZAB協議中,這就是zxid。ZAB協議中,消息的編號只能由Leader節點來分配,這樣的好處是我們就可以通過zxid來準確判斷事件發生的先後,記住,是任意事件,這也是分佈式系統中,由全局唯一的主節點來處理更新事件帶來的極大好處。

分佈式系統運行的過程中,Leader節點必然會發生改變,一致性協議必須能夠正確處理這種情況,保證在Leader發生變化的時候,新的Leader期間,產生的zxid必須要大於老的Leader時生成的zxid。這就得通過上面說的epoch機制了,具體實現會在下面的選主過程中詳細描述。

3、服務器ID:

比如有三臺服務器,編號分別是1,2,3,編號越大在選擇算法中的權重越大。另外zxid值越大說明數據越新,在選舉算法中數據越新權重越大。zxid的權重大於服務器ID;

4、集羣中節點狀態:

LOOKING: 節點正處於選主狀態,不對外提供服務,直至選主結束;

FOLLOWING: 作爲系統的從節點,接受主節點的更新並寫入本地日誌;

LEADING: 作爲系統主節點,接受客戶端更新,寫入本地日誌並複製到從節點;

5、消息廣播:

ZAB協議的消息廣播過程使用的是一個原子廣播協議,類似一個二階段提交過程。

Step1對於客戶端發送的寫請求,全部由Leader接收,Leader接收到寫請求消息請求後,將客戶端的寫請求消息,賦予一個全局唯一的64位自增id,叫:zxid,通過zxid的大小比較就可以實現因果有序這個特徵。Leader 爲每個follower準備了一個FIFO隊列(通過TCP協議來實現,以實現全局有序這一個特點)將帶有zxid的客戶端的寫請求封裝成一個事務 Proposal,作爲一個提案(proposal)分發給所有的 follower。 

Step2當follower接收到proposal,先把proposal寫到磁盤,寫入成功以後再向leader回覆一個ack。

Step3如果Leader接收到Follower超過半數的成功ACk響應。

Step4則向Follower發送commit消息,執行 commit 操作(先提交自己Leader的事務 Proposal(即執行客戶端發送的寫請求),再發送 commit 給所有 Follwer,讓所有的Follwer也執行commit操作)。

6、簡述選主過程:

啓動時選主,假如目前有5臺服務器,每臺服務器均沒有數據,它們的編號分別是1,2,3,4,5,按編號依次啓動,它們的選擇舉過程如下:

1、服務器1啓動,給自己投票,然後發投票信息,由於其它機器還沒有啓動所以它收不到反饋信息,服務器1的狀態一直屬於Looking;
2、服務器2啓動,給自己投票,同時與之前啓動的服務器1交換結果,由於服務器2的編號大所以服務器2勝出,但此時投票數沒有大於半數,所以兩個服務器的狀態依然是LOOKING;
3、服務器3啓動,給自己投票,同時與之前啓動的服務器1,2交換信息,由於服務器3的編號最大所以服務器3勝出,此時投票數正好大於半數,所以服務器3成爲領導者,服務器1,2成爲小弟;
4、服務器4啓動,給自己投票,同時與之前啓動的服務器1,2,3交換信息,儘管服務器4的編號大,但之前服務器3已經勝出,所以服務器4只能成爲小弟;
5、服務器5啓動,後面的邏輯同服務器4成爲小弟;

節點異常選主和數據一致性同步,主要是以zxid值最大且已Commit的事務爲準,並同步集羣中節點數據一致性,有三種情況,一是Leader自己提交事物後宕機,宕機之前沒有給Follwer 執行Commit,此時重新選主,應刪除沒有Commit的zxid對應的事務。二是Follwer宕機,此時無需選主,Leader向運行Follwer執行Commit提交事務同步數據。三是集羣中某點宕機後重啓,再次加入集羣,此時無需選主,新節點加入就是Follwer,並且根據Leader的zxid同步數據。


綜上,Zookeeper集羣架構是主從模式,數據沒有分片,集羣中節點的數據是一樣的,選主時少數服從多數,所以集羣最好是單數,且最好大於3,集羣中某節點宕機不影響集羣工作,如果是Leader掛了,會重新選主。


以上所述,僅是Zookeeper簡單介紹,如果要詳細瞭解,可以去看Zookeeper源碼,請感興趣的朋友自己去了解,另外以上所寫,可能有一些問題,望留言糾正,或請加qq(907128466)羣一起學習討論,謝謝每位觀看到朋友!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章