Zookeeper簡介

Floatingshen發表於2020-12-10

zookeeper簡介及特點

ZooKeeper 是一個開源的分散式協調服務,ZooKeeper的設計目標是將那些複雜且容易出錯的分散式一致性服務封裝起來,構成一個高效可靠的原語集,並以一系列簡單易用的介面提供給使用者使用。

ZooKeeper 是一個典型的分散式資料一致性解決方案,分散式應用程式可以基於 ZooKeeper 實現諸如資料釋出/訂閱、負載均衡、命名服務、分散式協調/通知、叢集管理、Master 選舉、分散式鎖和分散式佇列等功能。

ZooKeeper 一個最常用的使用場景就是用於擔任服務生產者和服務消費者的註冊中心。 服務生產者將自己提供的服務註冊到 ZooKeeper 中心,服務的消費者在進行服務呼叫的時候先到 ZooKeeper 中查詢服務,獲取到服務生產者的詳細資訊之後,再去呼叫服務生產者的內容與資料。

特點:

  • 順序一致性:從同一客戶端發起的事務請求,最終將會嚴格地按照順序被應用到 ZooKeeper 中去。
  • 原子性:所有事務請求的處理結果在整個叢集中所有機器上的應用情況是一致的,也就是說,要麼整個叢集中所有的機器都成功應用了某一個事務,要麼都沒有應用。
  • 單一系統映像:無論客戶端連到哪一個 ZooKeeper 伺服器上,其看到的服務端資料模型都是一致的。
  • 可靠性:一旦一次更改請求被應用,更改的結果就會被持久化,直到被下一次更改覆蓋

zookeeper元素

session會話

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

客戶端啟動的時候,首先會與伺服器建立一個 TCP 連線,從第一次連線建立開始,客戶端會話的生命週期也開始了。

通過這個連線,客戶端能夠通過心跳檢測與伺服器保持有效的會話,也能夠向 Zookeeper 伺服器傳送請求並接受響應,同時還能夠通過該連線接收來自伺服器的 Watch 事件通知。

Session 的 sessionTimeout 值用來設定一個客戶端會話的超時時間。

當由於伺服器壓力太大、網路故障或是客戶端主動斷開連線等各種原因導致客戶端連線斷開時,只要在 sessionTimeout 規定的時間內能夠重新連線上叢集中任意一臺伺服器,那麼之前建立的會話仍然有效。

在為客戶端建立會話之前,服務端首先會為每個客戶端都分配一個 sessionID。

由於 sessionID 是 Zookeeper 會話的一個重要標識,許多與會話相關的執行機制都是基於這個 sessionID 的。

因此,無論是哪臺伺服器為客戶端分配的 sessionID,都務必保證全域性唯一。

節點

在談到分散式的時候,我們通常說的“節點"是指組成叢集的每一臺機器。

然而,在 ZooKeeper 中,“節點"分為兩類:

  1. 同樣是指構成叢集的機器,我們稱之為機器節點。
  2. 則是指資料模型中的資料單元,我們稱之為資料節點一ZNode。有以下四種型別
    • PERSISTENT:持久化節點
    • PERSISTENT_SEQUENTIAL:順序自動編號持久化節點
    • EPHEMERAL:臨時節點,跟著session,即session超時這類節點也會自動刪除
    • EPHEMERAL_SEQUENTIAL:臨時自動編號節點

zookeeper的節點有以下四種狀態:

  • LOOKING:尋找Leader狀態,處於該狀態需要進入選舉流程
  • LEADING:領導者狀態,處於該狀態的節點說明是角色已經是Leader
  • FOLLOWING:跟隨者狀態,表示Leader已經選舉出來,當前節點角色是follower
  • OBSERVER:觀察者狀態,表明當前節點角色是observer

ZooKeeper 將所有資料儲存在記憶體中,資料模型是一棵樹(Znode Tree),由斜槓(/)的進行分割的路徑,就是一個 Znode,例如/foo/path1。每個上都會儲存自己的資料內容,同時還會儲存一系列屬性資訊。

在 Zookeeper 中,Node 可以分為持久節點和臨時節點兩類。所謂持久節點是指一旦這個 ZNode 被建立了,除非主動進行 ZNode 的移除操作,否則這個 ZNode 將一直儲存在 ZooKeeper 上。

而臨時節點就不一樣了,它的生命週期和客戶端會話繫結,一旦客戶端會話失效,那麼這個客戶端建立的所有臨時節點都會被移除。

另外,ZooKeeper 還允許使用者為每個節點新增一個特殊的屬性:SEQUENTIAL。

一旦節點被標記上這個屬性,那麼在這個節點被建立的時候,ZooKeeper 會自動在其節點名後面追加上一個整型數字,這個整型數字是一個由父節點維護的自增數字。

版本

Zookeeper 的每個 ZNode 上都會儲存資料,對應於每個 ZNode,Zookeeper 都會為其維護一個叫作 Stat 的資料結構。

Stat 中記錄了這個 ZNode 的三個資料版本,分別是:

  • version(當前 ZNode 的版本)
  • cversion(當前 ZNode 子節點的版本)
  • aversion(當前 ZNode 的 ACL 版本)

Watcher監聽器

ZooKeeper 允許使用者在指定節點上註冊一些 Watcher,並且在一些特定事件觸發的時候,ZooKeeper 服務端會將事件通知到感興趣的客戶端上去,該機制是 ZooKeeper 實現分散式協調服務的重要特性。

ACL

ZooKeeper 採用 ACL(AccessControlLists)策略來進行許可權控制,類似於 UNIX 檔案系統的許可權控制。

ZooKeeper 定義了 5 種許可權:

  • CREATE:建立子節點的許可權
  • READ:獲取節點資料和子節點列表的許可權
  • WRITE:更新節點資料的許可權
  • DELETE:刪除子節點的許可權
  • ADMIN:設定節點ACL的許可權

其中CREATE和DELETE都是針對子節點的許可權

順序訪問

對於來自客戶端的每個更新請求,ZooKeeper 都會分配一個全域性唯一的遞增編號。

這個編號反應了所有事務操作的先後順序,應用程式可以使用 ZooKeeper 這個特性來實現更高層次的同步原語。這個編號也叫做時間戳—zxid(ZooKeeper Transaction Id)

分散式鎖

  1. 客戶端連線zookeeper,並在/lock下建立臨時的且有序的子節點,第一個客戶端對應的子節點為/lock/lock-0000000000,第二個為/lock/lock-0000000001,以此類推。
  2. 客戶端獲取/lock下的子節點列表,判斷自己建立的子節點是否為當前子節點列表中序號最小的子節點,如果是則認為獲得鎖,否則監聽/lock的子節點變更訊息,獲得子節點變更通知後重復此步驟直至獲得鎖;
  3. 執行業務程式碼;
  4. 完成業務流程後,刪除對應的子節點釋放鎖

zookeeper叢集

在Zookeeper叢集中,主要有三種角色,

  • Leader:既可以為客戶端提供寫服務又能提供讀服務。除了 Leader 外,Follower和Observer都只能提供讀服務
  • Follower:提供讀服務,並且參與選舉過程和寫操作的“過半寫成功”策略
  • Observer:提供讀服務

Zookeeper簡介

在zookeeper叢集中,我們通常採用奇數臺伺服器,一個最主要的原因在於防止腦裂

在叢集中,在選舉leader的時候,通常要超過一半以上才能被推舉為leader,選舉步驟如下:

  1. 每個Server發出一個投票。由於是初始情況,ZK1和ZK2都會將自己作為Leader伺服器來進行投票,每次投票會包含所推舉的伺服器的myid和ZXID,使用(myid, ZXID)來表示,此時ZK1的投票為(1, 0),ZK2的投票為(2,0),然後各自將這個投票傳送給叢集中的其它機器。
  2. 接受來自各個伺服器的投票。叢集的每個伺服器收到投票後,首先判斷該投票的有效性,如檢查是否是本輪投票、是否來自LOOKING狀態的伺服器。
  3. 處理投票。針對每一個投票,伺服器都需要將別人的投票和自己的投票進行比較,規則如下
    • 優先檢查ZXID。ZXID比較大的伺服器優先作為Leader。
    • 如果ZXID相同,那麼就比較myid。myid較大的伺服器作為Leader伺服器。 對於ZK1而言,它的投票是(1, 0),接收ZK2的投票為(2, 0),首先會比較兩者的ZXID,均為0,再比較myid,此時ZK2的myid最大,於是ZK2勝。ZK1更新自己的投票為(2, 0),並將投票重新傳送給ZK2。
  4. 統計投票。每次投票後,伺服器都會統計投票資訊,判斷是否已經有過半機器接受到相同的投票資訊,對於ZK1、ZK2而言,都統計出叢集中已經有兩臺機器接受了(2, 0)的投票資訊,此時便認為已經選出ZK2作為Leader。
  5. 改變伺服器狀態。一旦確定了Leader,每個伺服器就會更新自己的狀態,如果是Follower,那麼就變更為FOLLOWING,如果是Leader,就變更為LEADING。當新的Zookeeper節點ZK3啟動時,發現已經有Leader了,不再選舉,直接將直接的狀態從LOOKING改為FOLLOWING。

zookeeper協議

ZAB協議

ZAB(ZooKeeper Atomic Broadcast 原子廣播)協議是為分散式協調服務 ZooKeeper 專門設計的一種支援崩潰恢復的原子廣播協議。

在 ZooKeeper 中,主要依賴 ZAB 協議來實現分散式資料一致性,基於該協議,ZooKeeper 實現了一種主備模式的系統架構來保持叢集中各個副本之間的資料一致性。

ZAB 協議包括兩種基本的模式,分別是崩潰恢復訊息廣播

當整個服務框架在啟動過程中,或是當 Leader 伺服器出現網路中斷、崩潰退出與重啟等異常情況時,ZAB 協議就會進入恢復模式並選舉產生新的 Leader 伺服器。

當選舉產生了新的 Leader 伺服器,同時叢集中已經有過半的機器與該 Leader 伺服器完成了狀態同步之後,ZAB 協議就會退出恢復模式。

其中,所謂的狀態同步是指資料同步,用來保證叢集中存在過半的機器能夠和 Leader 伺服器的資料狀態保持一致。

當叢集中已經有過半的 Follower 伺服器完成了和 Leader 伺服器的狀態同步,那麼整個服務框架就可以進人訊息廣播模式了。

當一臺同樣遵守 ZAB 協議的伺服器啟動後加入到叢集中時,如果此時叢集中已經存在一個 Leader 伺服器在負責進行訊息廣播。

那麼新加入的伺服器就會自覺地進人資料恢復模式:找到 Leader 所在的伺服器,並與其進行資料同步,然後一起參與到訊息廣播流程中去。

正如上文介紹中所說的,ZooKeeper 設計成只允許唯一的一個 Leader 伺服器來進行事務請求的處理。

Leader 伺服器在接收到客戶端的事務請求後,會生成對應的事務提案併發起一輪廣播協議。

而如果叢集中的其他機器接收到客戶端的事務請求,那麼這些非 Leader 伺服器會首先將這個事務請求轉發給 Leader 伺服器。

zookeeper使用場景

  1. 分散式協調
    分散式協調技術主要用來解決分散式環境當中多個程式之間的同步控制,讓他們有序的去訪問某種臨界資源,防止造成"髒資料"的後果,可以使用分散式鎖實現。
  2. 後設資料/配置資訊管理
    比如kafka、storm、dubbo等都會將註冊資訊儲存到zookeeper中
  3. HA高可用性
    就是一個重要程式一般會做主備兩個,主程式掛了立馬通過 zookeeper 感知到切換到備用程式。

參考資料:

blog.csdn.net/chengyuqian… developer.51cto.com/art/201809/… blog.csdn.net/qiangcuo608…