Zookeeper(二):基本原理詳解

基本原理

因爲只是做下基礎知識的講解,加深對ZK的瞭解,所以,下面只講下ZK的兩個重要機制

  • 監聽機制
  • 選舉機制(ZK集羣)

一:監聽機制

道人畫了下簡圖(MarkDowm畫簡圖,真香!):

創建監聽
通知監聽對象發生變化
創建監聽
通知監聽對象發生變化
註冊,修改服務
client1
zk_service
client2
service
  • ZooKeeper 提供了分佈式數據發佈/訂閱功能,一個典型的發佈/訂閱模型系 統定義了一種一對多的訂閱關係,能讓多個訂閱者同時監聽某一個主題對象,當 這個主題對象自身狀態變化時,會通知所有訂閱者,使他們能夠做出相應的處理。
  • ZooKeeper 中,引入了 Watcher 機制來實現這種分佈式的通知功能。 ZooKeeper 允許客戶端向服務端註冊一個 Watcher 監聽,當服務端的一些事件觸 發了這個 Watcher,那麼就會向指定客戶端發送一個事件通知來實現分佈式的通知功能。
  • 觸發事件種類很多,如:節點創建,節點刪除,節點改變,子節點改變等。

道人概括下,就是客戶端在ZK上指定節點創建監聽(監聽的觸發條件可以是節點創建,節點刪除,節點改變,子節點改變等),一旦節點發生改變觸發監聽,ZK會通知客戶端。

監聽機制的特點

  • 一次性觸發
    • 事件發生觸發監聽,一個watcher event就會被髮送到設置監聽的客戶端, 這種效果是一次 性的,後續再次發生同樣的事件,不會再次觸發。如果需要再次監聽同樣的事件,需要再次設置。
  • 事件封裝
    • ZooKeeper 使用 WatchedEvent 對象來封裝服務端事件並傳遞。 WatchedEvent 包含了每一個事件的三個基本屬性: 通知狀態(keeperState),事件類型(EventType)和節點路徑(path)
  • event 異步發送
    • watcher 的通知事件從服務端發送到客戶端是異步的
  • 先註冊再觸發
    • Zookeeper 中的 watch 機制,必須客戶端先去服務端註冊監聽,這樣事件發 送纔會觸發監聽,通知給客戶端。

道人概括下就是:

  • 客戶端先註冊監聽;且監聽只會被觸發一次(後失效),如果需要再次監聽需要再次設置;監聽觸發後,ZK將通知事件封裝異步傳遞客戶端。

監聽的命令操作,javaAPI會在道人的後續博客中介紹。

二:選舉機制

ZK集羣模式下,選取出Leader的方式,最新的算法是FastLeaderElection(默認),判斷依據是選票超過半數則選舉成功。

涉及概念

  • 服務器ID

    • 比如有三臺服務器,zk依次啓動時會對服務器進行依次編號分別是 1,2,3。 編號越大在選擇算法中的權重越大。(全新集羣選舉時,哪個ZK服務先啓動其sessionID越小。)
  • 選舉狀態

    • LOOKING,競選狀態。
    • FOLLOWING,隨從狀態,同步 leader 狀態,參與投票。
    • OBSERVING,觀察狀態, 同步 leader 狀態,不參與投票。
    • LEADING,領導者狀態。
  • 數據ID

服務器中存放的最新數據 version。
值越大說明數據越新,在選舉算法中數據越新權重越大。

  • 邏輯時鐘

也叫投票的次數,同一輪投票過程中的邏輯時鐘值是相同的。每投完一次票 這個數據就會增加,然後與接收到的其它服務器返回的投票信息中的數值相比, 根據不同的值做出不同的判斷。

選舉機制大致流程圖

ZK選舉流程圖

舉個栗子

在這裏插入圖片描述

首先道人介紹下選舉時幾個原則,幫助各位道友理解。

  • 每當一個ZK節點加入集羣中,獲取當前節點的Zxid(也是遞增),並使邏輯時鐘的值+1,新的ZK節點向其他節點廣播的邏輯時鐘值大於其保存的邏輯時鐘值,表明有新的節點加入集羣,便從新開始一次選舉。
  • 每個新加入節點,會將選票投給自己,同時通知其他節點從新投票,投票原則是,將票投給Zxid最大的節點(也可理解新加入節點)。
  • 判斷規則爲節點選票大於半數,則選擇的節點選舉爲leader,而一旦選舉爲leader,,自身狀態會變爲leading,其之前節點狀態會有Looking變爲Following則後續加入節點,不可能成爲leader,只能作爲Follower。

再簡化說下原則:

  • 原則一:選票投最大Zxid節點,**超過半數則選舉出Leader。**直到選舉出Leader,集羣才能正常工作。
  • 原則二:節點加入(Looking狀態),則開啓新一輪選舉,其他節點更改選票,根據原則一,判斷是否選舉出Leader。
  • 原則三:Leader選舉出來後,選舉爲Leader的節點狀態修改爲Leading,其他節點從Looking修改爲Following,後續節點均爲Follower

以五個節點的ZK服務集羣爲例(這裏的服務器後1,2,3,4,5;可以理解爲zk服務的Zxid)

(1)服務器1啓動,發起一次選舉。

服務器1投票給自己,發現選票小於半數,無法完成選舉。
服務器1狀態保持爲LOOKING;

(2)服務器2啓動,再發起一次選舉。

服務器1和2分別投自己一票,此時服務器1發現服務器2的Zxid比自己大,更改選票投給服務器2;

發現選票小於半數,無法完成選舉。

服務器1,2狀態保持爲LOOKING;

(3)服務器3啓動,發起一次選舉。

服務器1,2,3分別投自己一票,服務器1和服務器2更改選票投給Zxid更大的服務器3;

此次投票結果:服務器1爲0票,服務器2爲0票,服務器3爲3票。此時服務器3的票數已經超過半數(3票),服務器3當選Leader。

服務器1,2更改狀態爲FOLLOWING,服務器3更改狀態爲LEADING;

(4)服務器4啓動,發起一次選舉。

此時服務器1,2,3已經不是LOOKING狀態,不會更改選票信息。交換選票信息結果:服務器3爲3票,服務器4爲1票。

此時服務器4服從多數,更改選票信息爲服務器3;

服務器4並更改狀態爲FOLLOWING;

(5)服務器5啓動(情況與服務器5相同);

服務器5並更改狀態爲FOLLOWING;

上述過程的選舉流程圖如下:

在這裏插入圖片描述


上述講解的是全新集羣選舉(即集羣啓動時選舉的機制),下面介紹下非全新集羣選舉(集羣啓動後有節點宕機的情況)。

非全新集羣選舉

對於運行正常的 zookeeper 集羣,中途有節點宕機,需要重新選舉時, 選舉過程就需要加入數據 ID、服務器 ID 和邏輯時鐘。

概念:

  • 數據 ID:數據新的 version 就大,數據每次更新都會更新 version。
  • 服務器 ID:就是我們配置的 myid 中的值,每個機器一個。
  • 邏輯時鐘:這個值從 0 開始遞增,每次選舉對應一個值。 如果在同一次選舉 中,這個值是一致的。

選舉原則:

  • 邏輯時鐘小的選舉結果被忽略,重新投票;
  • 統一邏輯時鐘後,數據 id 大的勝出;
  • 數據 id 相同的情況下,服務器 id 大的勝出;

其餘選舉過程等同於全新集羣選舉。

道友們都看到這了,有收穫的話,點個贊再走唄!道人在此謝過了!
在這裏插入圖片描述

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