初識Zookeeper以及其中的選舉流程

語言: CN / TW / HK

知之為知之,不知為不知,是知也。

01、角色

  • Leader:

主要負責處理事務相關的操作,負責給Follower釋出命令,處理Follower的反饋資訊

負責同步訊息,將訊息同步到Follower中

可以保證事務處理的順序性

負責投票的發起以及更新系統的狀態

  • Follower:

負責參與投票選舉Leader

參與事務的Proposal請求的投票

將事務的執行結果反饋給Leader

  • Observer:

作為觀察者不參與Leader的選舉

負責將客戶端的寫請求轉發給Leader

02、會話

  • 會話是指zookeeper伺服器與客戶端的會話,在zookeeper中一個客戶端連線是指客戶端與服務端之間的TCP長連線。

  • 客戶端啟動時首先會與伺服器簡歷一個TCP建立一個連線,從建立這個連線開始,客戶端會話的生命週期就開始了。

  • 通過這個連線客戶端可以通過心跳檢測來保證與服務端之間的會話,也能夠向zookeeper伺服器傳送請求並接受響應,還可以接收伺服器的Watch事件通知。

  • 如果因為故障等原因導致客戶端連線斷開,那麼在sessionTimeout規定的時間內能夠重新連線上叢集中的任意一臺,那麼之前的會話仍然有效。

  • 為客戶端建立連線之前服務端會為客戶端分配一個sessionID,並且sessionID是唯一的。

03、節點

  • 臨時節點:臨時節點的生命週期和客戶端與服務端的會話進行保定,如果客戶端會話失效,那麼這個客戶端建立的所有臨時節點也會被移除。

  • 持久節點:一旦ZNode被建立除非執行ZNode移除操作,否則ZNode一直儲存在zookeeper上。

  • zookeeper將資料都儲存在記憶體中,儲存資料的模型是以一棵樹的形式進行儲存的

  • 在ZNode中,zookeeper都會為每個ZNode維護一個叫做Stat的資料結構,Stat中記錄ZNode的三個資料版本,分別是:

        1、version(當前ZNode版本)

        2、cversion(當前ZNode子節點的版本)

        3、aversion(當前ZNode的ACL版本)

04、Watcher(監聽)

  • 使用者使用zookeeper時可以在指定節點上註冊Watcher,並且當有特定事件觸發了這個Watcher時,zookeeper服務端會將這個事件通知到指定的客戶端中。

  • watch事件是一次性的,觸發結束就會消失。

  • 流程如下:

Watch是輕量級的,其實就是本地JVM的Callback,伺服器端只是存了是否有設定了Watcher的布林型別。(原始碼見:org.apache.zookeeper.server.FinalRequestProcessor)

在服務端,在FinalRequestProcessor處理對應的Znode操作時,會根據客戶端傳遞的watcher變數,新增到對應的ZKDatabase(org.apache.zookeeper.server.ZKDatabase)中進行持久化儲存,同時將自己NIOServerCnxn做為一個Watcher callback,監聽服務端事件變化

Leader通過投票通過了某次Znode變化的請求後,然後通知對應的Follower,Follower根據自己記憶體中的zkDataBase資訊,傳送notification資訊給zookeeper客戶端。

Zookeeper客戶端接收到notification資訊後,找到對應變化path的watcher列表,挨個進行觸發回撥。

05、ACL

zookeeper採用了ACL策略來實現許可權控制,這個ACL策略類似於UNIX檔案系統的許可權控制。

五種許可權分別為:

1、CREATE:建立子節點的許可權

2、READ:讀取節點資料以及子節點列表的許可權

3、WRITER:更新節點資料的許可權

4、DELETE:刪除子節點的許可權

5、ADMIN:設定節點ACL的許可權

06、特點

1、順序一致性:客戶端發出的請求會按照發出的順序傳送給zookeeper

2、原子性:zookeeper叢集要處理某個事務請求時,該事務在叢集中所有的處理結果都是一致的,也就是要麼該事務被所有zookeeper處理成功,只要有一個zookeeper沒有處理成功就全部失敗。

3、可靠性:一旦請求被應用,那麼該請求的結果就會被持久化,直到下一次的請求。

4、資料唯一性:在叢集中客戶端無論連線了哪個zookeeper獲取到的資料模型都是一樣的。

07、Zookeeper選舉流程

  • zookeeper叢集一般都是奇數臺,這是因為如果有三臺集器,那麼最多允許掛掉一臺,如果有四臺,那麼也是最多允許掛掉一臺,既然三臺 和四臺的容災能力是一樣的,那麼為了節省伺服器資源選擇奇數個數就可以。

  • 在zookeeper叢集中只要有任意一臺機器收到了半數以上的投票,那麼該機器就被選舉為Leader。

  • zookeeper的選舉通常是由zxid以及myid來決定誰是Leader。

  • zxid:zxid是一個64位的有規則的編號,在64位中高32位是epoch編號,低32位是訊息計數器,每收到一條提議(proposal),低32位的訊息計數器就會加1。epoch編號是選舉Leader的計數器,也就是每次投票選舉Leader操作都會進行加1。每產生一個Leader那麼epoch都會加1並且保證了唯一性,這樣也保證了Follower只聽從最新的epoch編號對應的Leader,就算舊的Leader崩潰恢復之後也不會有其它Follower聽從這個舊Leader了。

  • myid:myid是叢集中的機器標識,在叢集中每個機器都會分配一個唯一的myid。

  • 投票過程:在叢集中每個啟動的server的狀態都是LOOKING,然後開始執行選舉,每個server都會向其它server廣播投票,投票資訊中包含該server的myid和zxid(剛開始時myid和zxid都是自己),比如server1投的資訊為(1,0),server2投出的資訊為(2,0),server3投出的為(3,0)然後首先根據zxid來選舉誰是Leader,發現zxid都相同,那麼再根據myid,server1收到server2和server3的資訊,那麼根據myid會投票server3為Leader,server2收到server1和server3的,那麼也會投票server3,server3收到的投票超過半數,則選擇server3為Leader,最後立即改變叢集中各個server的狀態都為Following。(舉例比較單一也是為了方便理解,真實的投票選舉過程可以看paxos演算法選舉流程)

08、zab協議

1、崩潰恢復:當叢集中Leader宕機或者半數以上的Follower失去連線,那麼此時Leader就不是一個合法的Leader就需要重新選舉Leader,就需要進入崩潰恢復階段,崩潰恢復階段包括兩部分:Leader選舉和資料同步,Leader選舉階段負責選舉新的Leader,資料同步階段負責將Follower和Leader中的資料保持一致。

2、訊息廣播:

1、Leader收到客戶端的事務請求時會將該請求轉換為proposal,並且會為proposal生成一個唯一的zxid

2、Leader會為每一個Follower生成一個FIFO佇列,用來儲存Leader發出的proposal,並且Follower會按照FIFO順序接收(保證順序性)

3、Follower收到proposal然後將proposal寫入本地磁碟中,寫入成功後返回一個ack響應訊息給Leader。

4、Leader收到超過半數的ack響應訊息後,則認為訊息傳送成功,可以commit事務

5、Leader向所有的Follower傳送commit訊息,同時自身也會完成事務的提交。Follower收到commit訊息則將proposal事務提交。