【入門】ZooKeeper 相關概念總結

1. 前言

相信你們對 ZooKeeper 應該不算陌生。可是你真的瞭解 ZooKeeper 到底有啥用不?若是別人/面試官讓你給他講講對於 ZooKeeper 的認識,你能回答到什麼地步呢?html

拿我本身來講吧!我本人曾經使用 Dubbo 來作分佈式項目的時候,使用了 ZooKeeper 做爲註冊中心。爲了保證分佈式系統可以同步訪問某個資源,我還使用 ZooKeeper 作過度布式鎖。另外,我在學習 Kafka 的時候,知道 Kafka 不少功能的實現依賴了 ZooKeeper。node

前幾天,總結項目經驗的時候,我忽然問本身 ZooKeeper 究竟是個什麼東西?想了半天,腦海中只是簡單的能浮現出幾句話:面試

  1. ZooKeeper 能夠被用做註冊中心、分佈式鎖;
  2. ZooKeeper 是 Hadoop 生態系統的一員;
  3. 構建 ZooKeeper 集羣的時候,使用的服務器最好是奇數臺。

因而可知,我對於 ZooKeeper 的理解僅僅是停留在了表面。算法

因此,經過本文,但願帶你們稍微詳細的瞭解一下 ZooKeeper 。若是沒有學過 ZooKeeper ,那麼本文將會是你進入 ZooKeeper 大門的墊腳磚。若是你已經接觸過 ZooKeeper ,那麼本文將帶你回顧一下 ZooKeeper 的一些基礎概念。shell

另外,本文不光會涉及到 ZooKeeper 的一些概念,後面的文章會介紹到 ZooKeeper 常見命令的使用以及使用 Apache Curator 做爲 ZooKeeper 的客戶端。服務器

若是文章有任何須要改善和完善的地方,歡迎在評論區指出,共同進步!網絡

2. ZooKeeper 介紹

2.1. ZooKeeper 由來

正式介紹 ZooKeeper 以前,咱們先來看看 ZooKeeper 的由來,還挺有意思的。session

下面這段內容摘自《從 Paxos 到 ZooKeeper 》第四章第一節,推薦你們閱讀一下:數據結構

ZooKeeper 最先起源於雅虎研究院的一個研究小組。在當時,研究人員發現,在雅虎內部不少大型系統基本都須要依賴一個相似的系統來進行分佈式協調,可是這些系統每每都存在分佈式單點問題。因此,雅虎的開發人員就試圖開發一個通用的無單點問題的分佈式協調框架,以便讓開發人員將精力集中在處理業務邏輯上。

關於「ZooKeeper」這個項目的名字,其實也有一段趣聞。在立項初期,考慮到以前內部不少項目都是使用動物的名字來命名的(例如著名的 Pig 項目),雅虎的工程師但願給這個項目也取一個動物的名字。時任研究院的首席科學家 RaghuRamakrishnan 開玩笑地說:「在這樣下去,咱們這兒就變成動物園了!」此話一出,你們紛紛表示就叫動物園管理員吧一一一由於各個以動物命名的分佈式組件放在一塊兒,雅虎的整個分佈式系統看上去就像一個大型的動物園了,而 ZooKeeper 正好要用來進行分佈式環境的協調一一因而,ZooKeeper 的名字也就由此誕生了。架構

2.2. ZooKeeper 概覽

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

原語: 操做系統或計算機網絡用語範疇。是由若干條指令組成的,用於完成必定功能的一個過程。具備不可分割性·即原語的執行必須是連續的,在執行過程當中不容許被中斷。

ZooKeeper 爲咱們提供了高可用、高性能、穩定的分佈式數據一致性解決方案,一般被用於實現諸如數據發佈/訂閱、負載均衡、命名服務、分佈式協調/通知、集羣管理、Master 選舉、分佈式鎖和分佈式隊列等功能。

另外,ZooKeeper 將數據保存在內存中,性能是很是棒的。 在「讀」多於「寫」的應用程序中尤爲地高性能,由於「寫」會致使全部的服務器間同步狀態。(「讀」多於「寫」是協調服務的典型場景)。

2.3. ZooKeeper 特色

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

2.4. ZooKeeper 典型應用場景

ZooKeeper 概覽中,咱們介紹到使用其一般被用於實現諸如數據發佈/訂閱、負載均衡、命名服務、分佈式協調/通知、集羣管理、Master 選舉、分佈式鎖和分佈式隊列等功能。

下面選 3 個典型的應用場景來專門說說:

  1. 分佈式鎖 : 經過建立惟一節點得到分佈式鎖,當得到鎖的一方執行完相關代碼或者是掛掉以後就釋放鎖。
  2. 命名服務 :能夠經過 ZooKeeper 的順序節點生成全局惟一 ID
  3. 數據發佈/訂閱 :經過 Watcher 機制 能夠很方便地實現數據發佈/訂閱。當你將數據發佈到 ZooKeeper 被監聽的節點上,其餘機器可經過監聽 ZooKeeper 上節點的變化來實現配置的動態更新。

實際上,這些功能的實現基本都得益於 ZooKeeper 能夠保存數據的功能,可是 ZooKeeper 不適合保存大量數據,這一點須要注意。

2.5. 有哪些著名的開源項目用到了 ZooKeeper?

  1. Kafka : ZooKeeper 主要爲 Kafka 提供 Broker 和 Topic 的註冊以及多個 Partition 的負載均衡等功能。
  2. Hbase : ZooKeeper 爲 Hbase 提供確保整個集羣只有一個 Master 以及保存和提供 regionserver 狀態信息(是否在線)等功能。
  3. Hadoop : ZooKeeper 爲 Namenode 提供高可用支持。

3. ZooKeeper 重要概念解讀

破音:拿出小本本,下面的內容很是重要哦!

3.1. Data model(數據模型)

ZooKeeper 數據模型採用層次化的多叉樹形結構,每一個節點上均可以存儲數據,這些數據能夠是數字、字符串或者是二級制序列。而且。每一個節點還能夠擁有 N 個子節點,最上層是根節點以「/」來表明。每一個數據節點在 ZooKeeper 中被稱爲 znode,它是 ZooKeeper 中數據的最小單元。而且,每一個 znode 都一個惟一的路徑標識。

強調一句:ZooKeeper 主要是用來協調服務的,而不是用來存儲業務數據的,因此不要放比較大的數據在 znode 上,ZooKeeper 給出的上限是每一個結點的數據大小最大是 1M。

從下圖能夠更直觀地看出:ZooKeeper 節點路徑標識方式和 Unix 文件系統路徑很是類似,都是由一系列使用斜槓"/"進行分割的路徑表示,開發人員能夠向這個節點中寫人數據,也能夠在節點下面建立子節點。這些操做咱們後面都會介紹到。

3.2. znode(數據節點)

介紹了 ZooKeeper 樹形數據模型以後,咱們知道每一個數據節點在 ZooKeeper 中被稱爲 znode,它是 ZooKeeper 中數據的最小單元。你要存放的數據就放在上面,是你使用 ZooKeeper 過程當中常常須要接觸到的一個概念。

3.2.1. znode 4種類型

咱們一般是將 znode 分爲 4 大類:

  • 持久(PERSISTENT)節點 :一旦建立就一直存在即便 ZooKeeper 集羣宕機,直到將其刪除。
  • 臨時(EPHEMERAL)節點 :臨時節點的生命週期是與 客戶端會話(session) 綁定的,會話消失則節點消失 。而且,臨時節點只能作葉子節點 ,不能建立子節點。
  • 持久順序(PERSISTENT_SEQUENTIAL)節點 :除了具備持久(PERSISTENT)節點的特性以外, 子節點的名稱還具備順序性。好比 /node1/app0000000001/node1/app0000000002
  • 臨時順序(EPHEMERAL_SEQUENTIAL)節點 :除了具有臨時(EPHEMERAL)節點的特性以外,子節點的名稱還具備順序性。

3.2.2. znode 數據結構

每一個 znode 由 2 部分組成:

  • stat :狀態信息
  • data : 節點存放的數據的具體內容

以下所示,我經過 get 命令來獲取 根目錄下的 dubbo 節點的內容。(get 命令在下面會介紹到)。

[zk: 127.0.0.1:2181(CONNECTED) 6] get /dubbo
# 該數據節點關聯的數據內容爲空
null
# 下面是該數據節點的一些狀態信息,其實就是 Stat 對象的格式化輸出
cZxid = 0x2
ctime = Tue Nov 27 11:05:34 CST 2018
mZxid = 0x2
mtime = Tue Nov 27 11:05:34 CST 2018
pZxid = 0x3
cversion = 1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 1

Stat 類中包含了一個數據節點的全部狀態信息的字段,包括事務 ID-cZxid、節點建立時間-ctime 和子節點個數-numChildren 等等。

下面咱們來看一下每一個 znode 狀態信息究竟表明的是什麼吧!(下面的內容來源於《從 Paxos 到 ZooKeeper 分佈式一致性原理與實踐》,由於 Guide 確實也不是特別清楚,要學會參考資料的嘛! ) :

znode 狀態信息 解釋
cZxid create ZXID,即該數據節點被建立時的事務 id
ctime create time,即該節點的建立時間
mZxid modified ZXID,即該節點最終一次更新時的事務 id
mtime modified time,即該節點最後一次的更新時間
pZxid 該節點的子節點列表最後一次修改時的事務 id,只有子節點列表變動纔會更新 pZxid,子節點內容變動不會更新
cversion 子節點版本號,當前節點的子節點每次變化時值增長 1
dataVersion 數據節點內容版本號,節點建立時爲 0,每更新一次節點內容(無論內容有無變化)該版本號的值增長 1
aclVersion 節點的 ACL 版本號,表示該節點 ACL 信息變動次數
ephemeralOwner 建立該臨時節點的會話的 sessionId;若是當前節點爲持久節點,則 ephemeralOwner=0
dataLength 數據節點內容長度
numChildren 當前節點的子節點個數

3.3. 版本(version)

在前面咱們已經提到,對應於每一個 znode,ZooKeeper 都會爲其維護一個叫做 Stat 的數據結構,Stat 中記錄了這個 znode 的三個相關的版本:

  • dataVersion :當前 znode 節點的版本號
  • cversion : 當前 znode 子節點的版本
  • aclVersion : 當前 znode 的 ACL 的版本。

3.4. ACL(權限控制)

ZooKeeper 採用 ACL(AccessControlLists)策略來進行權限控制,相似於 UNIX 文件系統的權限控制。

對於 znode 操做的權限,ZooKeeper 提供瞭如下 5 種:

  • CREATE : 能建立子節點
  • READ :能獲取節點數據和列出其子節點
  • WRITE : 能設置/更新節點數據
  • DELETE : 能刪除子節點
  • ADMIN : 能設置節點 ACL 的權限

其中尤爲須要注意的是,CREATEDELETE 這兩種權限都是針對 子節點 的權限控制。

對於身份認證,提供瞭如下幾種方式:

  • world : 默認方式,全部用戶均可無條件訪問。
  • auth :不使用任何 id,表明任何已認證的用戶。
  • digest :用戶名:密碼認證方式: username:password
  • ip : 對指定 ip 進行限制。

3.5. Watcher(事件監聽器)

Watcher(事件監聽器),是 ZooKeeper 中的一個很重要的特性。ZooKeeper 容許用戶在指定節點上註冊一些 Watcher,而且在一些特定事件觸發的時候,ZooKeeper 服務端會將事件通知到感興趣的客戶端上去,該機制是 ZooKeeper 實現分佈式協調服務的重要特性。

破音:很是有用的一個特性,都能出小本本記好了,後面用到 ZooKeeper 基本離不開 Watcher(事件監聽器)機制。

3.6. 會話(Session)

Session 能夠看做是 ZooKeeper 服務器與客戶端的之間的一個 TCP 長鏈接,經過這個鏈接,客戶端可以經過心跳檢測與服務器保持有效的會話,也可以向 ZooKeeper 服務器發送請求並接受響應,同時還可以經過該鏈接接收來自服務器的 Watcher 事件通知。

Session 有一個屬性叫作:sessionTimeoutsessionTimeout 表明會話的超時時間。當因爲服務器壓力太大、網絡故障或是客戶端主動斷開鏈接等各類緣由致使客戶端鏈接斷開時,只要在sessionTimeout規定的時間內可以從新鏈接上集羣中任意一臺服務器,那麼以前建立的會話仍然有效。

另外,在爲客戶端建立會話以前,服務端首先會爲每一個客戶端都分配一個 sessionID。因爲 sessionID是 ZooKeeper 會話的一個重要標識,許多與會話相關的運行機制都是基於這個 sessionID 的,所以,不管是哪臺服務器爲客戶端分配的 sessionID,都務必保證全局惟一。

4. ZooKeeper 集羣

爲了保證高可用,最好是以集羣形態來部署 ZooKeeper,這樣只要集羣中大部分機器是可用的(可以容忍必定的機器故障),那麼 ZooKeeper 自己仍然是可用的。一般 3 臺服務器就能夠構成一個 ZooKeeper 集羣了。ZooKeeper 官方提供的架構圖就是一個 ZooKeeper 集羣總體對外提供服務。

上圖中每個 Server 表明一個安裝 ZooKeeper 服務的服務器。組成 ZooKeeper 服務的服務器都會在內存中維護當前的服務器狀態,而且每臺服務器之間都互相保持着通訊。集羣間經過 ZAB 協議(ZooKeeper Atomic Broadcast)來保持數據的一致性。

最典型集羣模式: Master/Slave 模式(主備模式)。在這種模式中,一般 Master 服務器做爲主服務器提供寫服務,其餘的 Slave 服務器從服務器經過異步複製的方式獲取 Master 服務器最新的數據提供讀服務。

4.1. ZooKeeper 集羣角色

可是,在 ZooKeeper 中沒有選擇傳統的 Master/Slave 概念,而是引入了 Leader、Follower 和 Observer 三種角色。以下圖所示

ZooKeeper 集羣中的全部機器經過一個 Leader 選舉過程 來選定一臺稱爲 「Leader」 的機器,Leader 既能夠爲客戶端提供寫服務又能提供讀服務。除了 Leader 外,FollowerObserver 都只能提供讀服務。Follower 和 Observer 惟一的區別在於 Observer 機器不參與 Leader 的選舉過程,也不參與寫操做的「過半寫成功」策略,所以 Observer 機器能夠在不影響寫性能的狀況下提高集羣的讀性能。

角色 說明
Leader 爲客戶端提供讀和寫的服務,負責投票的發起和決議,更新系統狀態。
Follower 爲客戶端提供讀服務,若是是寫服務則轉發給 Leader。在選舉過程當中參與投票。
Observer 爲客戶端提供讀服務器,若是是寫服務則轉發給 Leader。不參與選舉過程當中的投票,也不參與「過半寫成功」策略。在不影響寫性能的狀況下提高集羣的讀性能。此角色於 ZooKeeper3.3 系列新增的角色。

當 Leader 服務器出現網絡中斷、崩潰退出與重啓等異常狀況時,就會進入 Leader 選舉過程,這個過程會選舉產生新的 Leader 服務器。

這個過程大體是這樣的:

  1. Leader election(選舉階段):節點在一開始都處於選舉階段,只要有一個節點獲得超半數節點的票數,它就能夠當選準 leader。
  2. Discovery(發現階段) :在這個階段,followers 跟準 leader 進行通訊,同步 followers 最近接收的事務提議。
  3. Synchronization(同步階段) :同步階段主要是利用 leader 前一階段得到的最新提議歷史,同步集羣中全部的副本。同步完成以後 準 leader 纔會成爲真正的 leader。
  4. Broadcast(廣播階段) :到了這個階段,ZooKeeper 集羣才能正式對外提供事務服務,而且 leader 能夠進行消息廣播。同時若是有新的節點加入,還須要對新節點進行同步。

4.2. ZooKeeper 集羣中的服務器狀態

  • LOOKING :尋找 Leader。
  • LEADING :Leader 狀態,對應的節點爲 Leader。
  • FOLLOWING :Follower 狀態,對應的節點爲 Follower。
  • OBSERVING :Observer 狀態,對應節點爲 Observer,該節點不參與 Leader 選舉。

4.3. ZooKeeper 集羣爲啥最好奇數臺?

ZooKeeper 集羣在宕掉幾個 ZooKeeper 服務器以後,若是剩下的 ZooKeeper 服務器個數大於宕掉的個數的話整個 ZooKeeper 才依然可用。假如咱們的集羣中有 n 臺 ZooKeeper 服務器,那麼也就是剩下的服務數必須大於 n/2。先說一下結論,2n 和 2n-1 的容忍度是同樣的,都是 n-1,你們能夠先本身仔細想想,這應該是一個很簡單的數學問題了。 好比假如咱們有 3 臺,那麼最大容許宕掉 1 臺 ZooKeeper 服務器,若是咱們有 4 臺的的時候也一樣只容許宕掉 1 臺。 假如咱們有 5 臺,那麼最大容許宕掉 2 臺 ZooKeeper 服務器,若是咱們有 6 臺的的時候也一樣只容許宕掉 2 臺。

綜上,何須增長那一個沒必要要的 ZooKeeper 呢?

5. ZAB 協議和Paxos 算法

Paxos 算法應該能夠說是 ZooKeeper 的靈魂了。可是,ZooKeeper 並無徹底採用 Paxos算法 ,而是使用 ZAB 協議做爲其保證數據一致性的核心算法。另外,在ZooKeeper的官方文檔中也指出,ZAB協議並不像 Paxos 算法那樣,是一種通用的分佈式一致性算法,它是一種特別爲Zookeeper設計的崩潰可恢復的原子消息廣播算法。

5.1. ZAB 協議介紹

ZAB(ZooKeeper Atomic Broadcast 原子廣播) 協議是爲分佈式協調服務 ZooKeeper 專門設計的一種支持崩潰恢復的原子廣播協議。 在 ZooKeeper 中,主要依賴 ZAB 協議來實現分佈式數據一致性,基於該協議,ZooKeeper 實現了一種主備模式的系統架構來保持集羣中各個副本之間的數據一致性。

5.2. ZAB 協議兩種基本的模式:崩潰恢復和消息廣播

ZAB 協議包括兩種基本的模式,分別是

  • 崩潰恢復 :當整個服務框架在啓動過程當中,或是當 Leader 服務器出現網絡中斷、崩潰退出與重啓等異常狀況時,ZAB 協議就會進入恢復模式並選舉產生新的Leader服務器。當選舉產生了新的 Leader 服務器,同時集羣中已經有過半的機器與該Leader服務器完成了狀態同步以後,ZAB協議就會退出恢復模式。其中,所謂的狀態同步是指數據同步,用來保證集羣中存在過半的機器可以和Leader服務器的數據狀態保持一致
  • 消息廣播當集羣中已經有過半的Follower服務器完成了和Leader服務器的狀態同步,那麼整個服務框架就能夠進入消息廣播模式了。 當一臺一樣遵照ZAB協議的服務器啓動後加入到集羣中時,若是此時集羣中已經存在一個Leader服務器在負責進行消息廣播,那麼新加入的服務器就會自覺地進入數據恢復模式:找到Leader所在的服務器,並與其進行數據同步,而後一塊兒參與到消息廣播流程中去。

關於 ZAB 協議&Paxos算法 須要講和理解的東西太多了,具體能夠看下面這兩篇文章:

6. 總結

  1. ZooKeeper 自己就是一個分佈式程序(只要半數以上節點存活,ZooKeeper 就能正常服務)。
  2. 爲了保證高可用,最好是以集羣形態來部署 ZooKeeper,這樣只要集羣中大部分機器是可用的(可以容忍必定的機器故障),那麼 ZooKeeper 自己仍然是可用的。
  3. ZooKeeper 將數據保存在內存中,這也就保證了 高吞吐量和低延遲(可是內存限制了可以存儲的容量不太大,此限制也是保持 znode 中存儲的數據量較小的進一步緣由)。
  4. ZooKeeper 是高性能的。 在「讀」多於「寫」的應用程序中尤爲地明顯,由於「寫」會致使全部的服務器間同步狀態。(「讀」多於「寫」是協調服務的典型場景。)
  5. ZooKeeper 有臨時節點的概念。 當建立臨時節點的客戶端會話一直保持活動,瞬時節點就一直存在。而當會話終結時,瞬時節點被刪除。持久節點是指一旦這個 znode 被建立了,除非主動進行 znode 的移除操做,不然這個 znode 將一直保存在 ZooKeeper 上。
  6. ZooKeeper 底層其實只提供了兩個功能:① 管理(存儲、讀取)用戶程序提交的數據;② 爲用戶程序提供數據節點監聽服務。

7. 參考

  1. 《從 Paxos 到 ZooKeeper 分佈式一致性原理與實踐》
相關文章
相關標籤/搜索