天天看點

資料搜集-JAVA系統的梳理知識19-Zookeeper

![](http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-9-10/56385654.jpg)
## 前言

相信大家對 ZooKeeper 應該不算陌生。但是你真的了解 ZooKeeper 是個什麼東西嗎?如果别人/面試官讓你給他講講  ZooKeeper 是個什麼東西,你能回答到什麼地步呢?

我本人曾經使用過 ZooKeeper 作為 Dubbo 的注冊中心,另外在搭建 solr 叢集的時候,我使用到了  ZooKeeper 作為 solr 叢集的管理工具。前幾天,總結項目經驗的時候,我突然問自己 ZooKeeper 到底是個什麼東西?想了半天,腦海中隻是簡單的能浮現出幾句話:“①Zookeeper 可以被用作注冊中心。 ②Zookeeper 是 Hadoop 生态系統的一員;③建構 Zookeeper 叢集的時候,使用的伺服器最好是奇數台。” 可見,我對于 Zookeeper 的了解僅僅是停留在了表面。

是以,**通過本文,希望帶大家稍微詳細的了解一下 ZooKeeper 。如果沒有學過 ZooKeeper ,那麼本文将會是你進入 ZooKeeper 大門的墊腳磚。如果你已經接觸過 ZooKeeper ,那麼本文将帶你回顧一下 ZooKeeper 的一些基礎概念。**

最後,**本文隻涉及 ZooKeeper 的一些概念,并不涉及 ZooKeeper 的使用以及 ZooKeeper 叢集的搭建。** 網上有介紹 ZooKeeper 的使用以及搭建 ZooKeeper 叢集的文章,大家有需要可以自行查閱。

## 一 什麼是 ZooKeeper

### ZooKeeper 的由來

**下面這段内容摘自《從Paxos到Zookeeper 》第四章第一節的某段内容,推薦大家閱讀以下:**

> Zookeeper最早起源于雅虎研究院的一個研究小組。在當時,研究人員發現,在雅虎内部很多大型系統基本都需要依賴一個類似的系統來進行分布式協調,但是這些系統往往都存在分布式單點問題。是以,**雅虎的開發人員就試圖開發一個通用的無單點問題的分布式協調架構,以便讓開發人員将精力集中在處理業務邏輯上。**
>
>關于“ZooKeeper”這個項目的名字,其實也有一段趣聞。在立項初期,考慮到之前内部很多項目都是使用動物的名字來命名的(例如著名的Pig項目),雅虎的工程師希望給這個項目也取一個動物的名字。時任研究院的首席科學家RaghuRamakrishnan開玩笑地說:“在這樣下去,我們這兒就變成動物園了!”此話一出,大家紛紛表示就叫動物園管理者吧一一一因為各個以動物命名的分布式元件放在一起,**雅虎的整個分布式系統看上去就像一個大型的動物園了,而Zookeeper正好要用來進行分布式環境的協調一一于是,Zookeeper的名字也就由此誕生了。**


### 1.1 ZooKeeper 概覽

ZooKeeper 是一個開源的分布式協調服務,ZooKeeper架構最初是在“Yahoo!"上建構的,用于以簡單而穩健的方式通路他們的應用程式。 後來,Apache ZooKeeper成為Hadoop,HBase和其他分布式架構使用的有組織服務的标準。 例如,Apache HBase使用ZooKeeper跟蹤分布式資料的狀态。**ZooKeeper 的設計目标是将那些複雜且容易出錯的分布式一緻性服務封裝起來,構成一個高效可靠的原語集,并以一系列簡單易用的接口提供給使用者使用。**

> **原語:** 作業系統或計算機網絡用語範疇。是由若幹條指令組成的,用于完成一定功能的一個過程。具有不可分割性·即原語的執行必須是連續的,在執行過程中不允許被中斷。

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

**Zookeeper 一個最常用的使用場景就是用于擔任服務生産者和服務消費者的注冊中心(提供釋出訂閱服務)。** 服務生産者将自己提供的服務注冊到Zookeeper中心,服務的消費者在進行服務調用的時候先到Zookeeper中查找服務,擷取到服務生産者的詳細資訊之後,再去調用服務生産者的内容與資料。如下圖所示,在 Dubbo架構中 Zookeeper 就擔任了注冊中心這一角色。

![Dubbo](http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-9-10/35571782.jpg)

### 1.2 結合個人使用情況的講一下 ZooKeeper

在我自己做過的項目中,主要使用到了 ZooKeeper 作為 Dubbo 的注冊中心(Dubbo 官方推薦使用 ZooKeeper注冊中心)。另外在搭建 solr 叢集的時候,我使用  ZooKeeper 作為 solr 叢集的管理工具。這時,ZooKeeper 主要提供下面幾個功能:1、叢集管理:容錯、負載均衡。2、配置檔案的集中管理3、叢集的入口。


我個人覺得在使用 ZooKeeper 的時候,最好是使用 叢集版的 ZooKeeper 而不是單機版的。官網給出的架構圖就描述的是一個叢集版的 ZooKeeper 。通常 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呢?

## 二 關于 ZooKeeper  的一些重要概念

### 2.1 重要概念總結

- **ZooKeeper  本身就是一個分布式程式(隻要半數以上節點存活,ZooKeeper  就能正常服務)。**
- **為了保證高可用,最好是以叢集形态來部署 ZooKeeper,這樣隻要叢集中大部分機器是可用的(能夠容忍一定的機器故障),那麼 ZooKeeper 本身仍然是可用的。**
- **ZooKeeper  将資料儲存在記憶體中,這也就保證了 高吞吐量和低延遲**(但是記憶體限制了能夠存儲的容量不太大,此限制也是保持znode中存儲的資料量較小的進一步原因)。
- **ZooKeeper 是高性能的。 在“讀”多于“寫”的應用程式中尤其地高性能,因為“寫”會導緻所有的伺服器間同步狀态。**(“讀”多于“寫”是協調服務的典型場景。)
- **ZooKeeper有臨時節點的概念。 當建立臨時節點的用戶端會話一直保持活動,瞬時節點就一直存在。而當會話終結時,瞬時節點被删除。持久節點是指一旦這個ZNode被建立了,除非主動進行ZNode的移除操作,否則這個ZNode将一直儲存在Zookeeper上。**
- ZooKeeper 底層其實隻提供了兩個功能:①管理(存儲、讀取)使用者程式送出的資料;②為使用者程式提供資料節點監聽服務。

**下面關于會話(Session)、 Znode、版本、Watcher、ACL概念的總結都在《從Paxos到Zookeeper 》第四章第一節以及第七章第八節有提到,感興趣的可以看看!**

### 2.2 會話(Session)

Session 指的是 ZooKeeper  伺服器與用戶端會話。**在 ZooKeeper 中,一個用戶端連接配接是指用戶端和伺服器之間的一個 TCP 長連接配接**。用戶端啟動的時候,首先會與伺服器建立一個 TCP 連接配接,從第一次連接配接建立開始,用戶端會話的生命周期也開始了。**通過這個連接配接,用戶端能夠通過心跳檢測與伺服器保持有效的會話,也能夠向Zookeeper伺服器發送請求并接受響應,同時還能夠通過該連接配接接收來自伺服器的Watch事件通知。** Session的`sessionTimeout`值用來設定一個用戶端會話的逾時時間。當由于伺服器壓力太大、網絡故障或是用戶端主動斷開連接配接等各種原因導緻用戶端連接配接斷開時,**隻要在`sessionTimeout`規定的時間内能夠重新連接配接上叢集中任意一台伺服器,那麼之前建立的會話仍然有效。**

**在為用戶端建立會話之前,服務端首先會為每個用戶端都配置設定一個sessionID。由于 sessionID 是 Zookeeper 會話的一個重要辨別,許多與會話相關的運作機制都是基于這個 sessionID 的,是以,無論是哪台伺服器為用戶端配置設定的 sessionID,都務必保證全局唯一。**

### 2.3 Znode

**在談到分布式的時候,我們通常說的“節點"是指組成叢集的每一台機器。然而,在Zookeeper中,“節點"分為兩類,第一類同樣是指構成叢集的機器,我們稱之為機器節點;第二類則是指資料模型中的資料單元,我們稱之為資料節點一一ZNode。**

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

**在Zookeeper中,node可以分為持久節點和臨時節點兩類。所謂持久節點是指一旦這個ZNode被建立了,除非主動進行ZNode的移除操作,否則這個ZNode将一直儲存在Zookeeper上。而臨時節點就不一樣了,它的生命周期和用戶端會話綁定,一旦用戶端會話失效,那麼這個用戶端建立的所有臨時節點都會被移除。** 另外,ZooKeeper還允許使用者為每個節點添加一個特殊的屬性:**SEQUENTIAL**.一旦節點被标記上這個屬性,那麼在這個節點被建立的時候,Zookeeper會自動在其節點名後面追加上一個整型數字,這個整型數字是一個由父節點維護的自增數字。

### 2.4 版本

在前面我們已經提到,Zookeeper 的每個 ZNode 上都會存儲資料,對應于每個ZNode,Zookeeper 都會為其維護一個叫作 **Stat** 的資料結構,Stat 中記錄了這個 ZNode 的三個資料版本,分别是version(目前ZNode的版本)、cversion(目前ZNode子節點的版本)和 aversion(目前ZNode的ACL版本)。


### 2.5 Watcher

**Watcher(事件監聽器),是Zookeeper中的一個很重要的特性。Zookeeper允許使用者在指定節點上注冊一些Watcher,并且在一些特定事件觸發的時候,ZooKeeper服務端會将事件通知到感興趣的用戶端上去,該機制是Zookeeper實作分布式協調服務的重要特性。**

### 2.6 ACL

Zookeeper采用ACL(AccessControlLists)政策來進行權限控制,類似于 UNIX 檔案系統的權限控制。Zookeeper 定義了如下5種權限。

![](http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-9-10/27473480.jpg)

其中尤其需要注意的是,CREATE和DELETE這兩種權限都是針對子節點的權限控制。

## 三 ZooKeeper 特點

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

## 四 ZooKeeper 設計目标

### 4.1 簡單的資料模型

ZooKeeper 允許分布式程序通過共享的層次結構命名空間進行互相協調,這與标準檔案系統類似。 名稱空間由 ZooKeeper 中的資料寄存器組成 - 稱為znode,這些類似于檔案和目錄。 與為存儲設計的典型檔案系統不同,ZooKeeper資料儲存在記憶體中,這意味着ZooKeeper可以實作高吞吐量和低延遲。

![](http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-9-10/94251757.jpg)

### 4.2 可建構叢集

**為了保證高可用,最好是以叢集形态來部署 ZooKeeper,這樣隻要叢集中大部分機器是可用的(能夠容忍一定的機器故障),那麼zookeeper本身仍然是可用的。** 用戶端在使用 ZooKeeper 時,需要知道叢集機器清單,通過與叢集中的某一台機器建立 TCP 連接配接來使用服務,用戶端使用這個TCP連結來發送請求、擷取結果、擷取監聽事件以及發送心跳包。如果這個連接配接異常斷開了,用戶端可以連接配接到另外的機器上。

**ZooKeeper 官方提供的架構圖:**

![](http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-9-10/68900686.jpg)

上圖中每一個Server代表一個安裝Zookeeper服務的伺服器。組成 ZooKeeper 服務的伺服器都會在記憶體中維護目前的伺服器狀态,并且每台伺服器之間都互相保持着通信。叢集間通過 Zab 協定(Zookeeper Atomic Broadcast)來保持資料的一緻性。

### 4.3 順序通路

**對于來自用戶端的每個更新請求,ZooKeeper 都會配置設定一個全局唯一的遞增編号,這個編号反應了所有事務操作的先後順序,應用程式可以使用 ZooKeeper 這個特性來實作更高層次的同步原語。** **這個編号也叫做時間戳——zxid(Zookeeper Transaction Id)**

### 4.4 高性能

**ZooKeeper 是高性能的。 在“讀”多于“寫”的應用程式中尤其地高性能,因為“寫”會導緻所有的伺服器間同步狀态。(“讀”多于“寫”是協調服務的典型場景。)**

## 五 ZooKeeper 叢集角色介紹

**最典型叢集模式: Master/Slave 模式(主備模式)**。在這種模式中,通常 Master伺服器作為主伺服器提供寫服務,其他的 Slave 伺服器從伺服器通過異步複制的方式擷取 Master 伺服器最新的資料提供讀服務。

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

![](http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-9-10/89602762.jpg)

 **ZooKeeper 叢集中的所有機器通過一個 Leader 選舉過程來標明一台稱為 “Leader” 的機器,Leader 既可以為用戶端提供寫服務又能提供讀服務。除了 Leader 外,Follower 和  Observer 都隻能提供讀服務。Follower 和  Observer 唯一的差別在于 Observer 機器不參與 Leader 的選舉過程,也不參與寫操作的“過半寫成功”政策,是以 Observer 機器可以在不影響寫性能的情況下提升叢集的讀性能。**

![](http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-9-13/91622395.jpg)

**當 Leader 伺服器出現網絡中斷、崩潰退出與重新開機等異常情況時,ZAB 協定就會進人恢複模式并選舉産生新的Leader伺服器。這個過程大緻是這樣的:**

1. Leader election(選舉階段):節點在一開始都處于選舉階段,隻要有一個節點得到超半數節點的票數,它就可以當選準 leader。
2. Discovery(發現階段):在這個階段,followers 跟準 leader 進行通信,同步 followers 最近接收的事務提議。
3. Synchronization(同步階段):同步階段主要是利用 leader 前一階段獲得的最新提議曆史,同步叢集中所有的副本。同步完成之後
準 leader 才會成為真正的 leader。
4. Broadcast(廣播階段)
到了這個階段,Zookeeper 叢集才能正式對外提供事務服務,并且 leader 可以進行消息廣播。同時如果有新的節點加入,還需要對新節點進行同步。

## 六 ZooKeeper &ZAB 協定&Paxos算法

### 6.1 ZAB 協定&Paxos算法

Paxos 算法應該可以說是  ZooKeeper 的靈魂了。但是,ZooKeeper 并沒有完全采用 Paxos算法 ,而是使用 ZAB 協定作為其保證資料一緻性的核心算法。另外,在ZooKeeper的官方文檔中也指出,ZAB協定并不像 Paxos 算法那樣,是一種通用的分布式一緻性算法,它是一種特别為Zookeeper設計的崩潰可恢複的原子消息廣播算法。

### 6.2 ZAB 協定介紹

**ZAB(ZooKeeper Atomic Broadcast 原子廣播) 協定是為分布式協調服務 ZooKeeper 專門設計的一種支援崩潰恢複的原子廣播協定。 在 ZooKeeper 中,主要依賴 ZAB 協定來實作分布式資料一緻性,基于該協定,ZooKeeper 實作了一種主備模式的系統架構來保持叢集中各個副本之間的資料一緻性。**

### 6.3 ZAB 協定兩種基本的模式:崩潰恢複和消息廣播

ZAB協定包括兩種基本的模式,分别是 **崩潰恢複和消息廣播**。當整個服務架構在啟動過程中,或是當 Leader 伺服器出現網絡中斷、崩潰退出與重新開機等異常情況時,ZAB 協定就會進人恢複模式并選舉産生新的Leader伺服器。當選舉産生了新的 Leader 伺服器,同時叢集中已經有過半的機器與該Leader伺服器完成了狀态同步之後,ZAB協定就會退出恢複模式。其中,**所謂的狀态同步是指資料同步,用來保證叢集中存在過半的機器能夠和Leader伺服器的資料狀态保持一緻**。

**當叢集中已經有過半的Follower伺服器完成了和Leader伺服器的狀态同步,那麼整個服務架構就可以進人消息廣播模式了。** 當一台同樣遵守ZAB協定的伺服器啟動後加人到叢集中時,如果此時叢集中已經存在一個Leader伺服器在負責進行消息廣播,那麼新加人的伺服器就會自覺地進人資料恢複模式:找到Leader所在的伺服器,并與其進行資料同步,然後一起參與到消息廣播流程中去。正如上文介紹中所說的,ZooKeeper設計成隻允許唯一的一個Leader伺服器來進行事務請求的處理。Leader伺服器在接收到用戶端的事務請求後,會生成對應的事務提案并發起一輪廣播協定;而如果叢集中的其他機器接收到用戶端的事務請求,那麼這些非Leader伺服器會首先将這個事務請求轉發給Leader伺服器。

關于 **ZAB 協定&Paxos算法** 需要講和了解的東西太多了,說實話,筆主到現在不太清楚這倆兄弟的具體原理和實作過程。推薦閱讀下面兩篇文章:

-  [圖解 Paxos 一緻性協定](http://codemacro.com/2014/10/15/explain-poxos/)
-  [Zookeeper ZAB 協定分析](https://dbaplus.cn/news-141-1875-1.html)

關于如何使用 zookeeper 實作分布式鎖,可以檢視下面這篇文章:

-  
[10分鐘看懂!基于Zookeeper的分布式鎖](
## 六 總結

通過閱讀本文,想必大家已從 **①ZooKeeper的由來。** -> **②ZooKeeper 到底是什麼 。**-> **③ ZooKeeper 的一些重要概念**(會話(Session)、 Znode、版本、Watcher、ACL)-> **④ZooKeeper 的特點。** -> **⑤ZooKeeper 的設計目标。**-> **⑥ ZooKeeper 叢集角色介紹** (Leader、Follower 和 Observer 三種角色)-> **⑦ZooKeeper &ZAB 協定&Paxos算法。** 這七點了解了 ZooKeeper 。

## 參考

- 《從Paxos到Zookeeper 》
- https://cwiki.apache.org/confluence/display/ZOOKEEPER/ProjectDescription
- https://cwiki.apache.org/confluence/display/ZOOKEEPER/Index
-
- https://zhuanlan.zhihu.com/p/30024403      
<!-- MarkdownTOC -->

- [ZooKeeper 資料模型](#zookeeper-資料模型)
- [ZNode\(資料節點\)的結構](#znode資料節點的結構)
- [測試 ZooKeeper 中的常見操作](#測試-zookeeper-中的常見操作)
  - [連接配接 ZooKeeper 服務](#連接配接-zookeeper-服務)
  - [檢視常用指令\(help 指令\)](#檢視常用指令help-指令)
  - [建立節點\(create 指令\)](#建立節點create-指令)
  - [更新節點資料内容\(set 指令\)](#更新節點資料内容set-指令)
  - [擷取節點的資料\(get 指令\)](#擷取節點的資料get-指令)
  - [檢視某個目錄下的子節點\(ls 指令\)](#檢視某個目錄下的子節點ls-指令)
  - [檢視節點狀态\(stat 指令\)](#檢視節點狀态stat-指令)
  - [檢視節點資訊和狀态\(ls2 指令\)](#檢視節點資訊和狀态ls2-指令)
  - [删除節點\(delete 指令\)](#删除節點delete-指令)
- [參考](#參考)

<!-- /MarkdownTOC -->

> 看本文之前如果你沒有安裝 ZooKeeper 的話,可以參考這篇文章:[《使用 SpringBoot+Dubbo 搭建一個簡單分布式服務》](https://github.com/Snailclimb/springboot-integration-examples/blob/master/md/springboot-dubbo.md) 的 “開始實戰 1 :zookeeper 環境安裝搭建” 這部分進行安裝(Centos7.4 環境下)。如果你想對 ZooKeeper 有一個整體了解的話,可以參考這篇文章:[《可能是把 ZooKeeper 概念講的最清楚的一篇文章》](https://github.com/Snailclimb/JavaGuide/blob/master/%E4%B8%BB%E6%B5%81%E6%A1%86%E6%9E%B6/ZooKeeper.md)

### ZooKeeper 資料模型

ZNode(資料節點)是 ZooKeeper 中資料的最小單元,每個ZNode上都可以儲存資料,同時還是可以有子節點(這就像樹結構一樣,如下圖所示)。可以看出,節點路徑辨別方式和Unix檔案
系統路徑非常相似,都是由一系列使用斜杠"/"進行分割的路徑表示,開發人員可以向這個節點中寫人資料,也可以在節點下面建立子節點。這些操作我們後面都會介紹到。
![ZooKeeper 資料模型](https://images.gitbook.cn/95a192b0-1c56-11e9-9a8e-f3b01b1ea9aa)

提到 ZooKeeper 資料模型,還有一個不得不得提的東西就是 **事務 ID** 。事務的ACID(Atomic:原子性;Consistency:一緻性;Isolation:隔離性;Durability:持久性)四大特性我在這裡就不多說了,相信大家也已經挺膩了。

在Zookeeper中,事務是指能夠改變 ZooKeeper 伺服器狀态的操作,我們也稱之為事務操作或更新操作,一般包括資料節點建立與删除、資料節點内容更新和用戶端會話建立與失效等操作。**對于每一個事務請求,ZooKeeper 都會為其配置設定一個全局唯一的事務ID,用 ZXID 來表示**,通常是一個64位的數字。每一個ZXID對應一次更新操作,**從這些 ZXID 中可以間接地識别出Zookeeper處理這些更新操作請求的全局順序**。

### ZNode(資料節點)的結構

每個 ZNode 由2部分組成:

- stat:狀态資訊
- data:資料内容

如下所示,我通過 get 指令來擷取 根目錄下的 dubbo 節點的内容。(get 指令在下面會介紹到)

```shell
[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 對象的格式化輸出。Stat 類中包含了一個資料節點的所有狀态資訊的字段,包括事務ID、版本資訊和子節點個數等,如下圖所示(圖源:《從Paxos到Zookeeper  分布式一緻性原理與實踐》,下面會介紹通過 stat 指令檢視資料節點的狀态)。

**Stat 類:**

![Stat 類](https://images.gitbook.cn/a841e740-1c55-11e9-b5b7-abf0ec0c666a)

關于資料節點的狀态資訊說明(也就是對Stat 類中的各字段進行說明),可以參考下圖(圖源:《從Paxos到Zookeeper  分布式一緻性原理與實踐》)。

![資料節點的狀态資訊說明](https://images.gitbook.cn/f44d8630-1c55-11e9-b5b7-abf0ec0c666a)

### 測試 ZooKeeper 中的常見操作


#### 連接配接 ZooKeeper 服務

進入安裝 ZooKeeper檔案夾的 bin 目錄下執行下面的指令連接配接 ZooKeeper 服務(Linux環境下)(連接配接之前首選要确定你的 ZooKeeper 服務已經啟動成功)。

```shell
./zkCli.sh -server 127.0.0.1:2181
```
![連接配接 ZooKeeper 服務](https://images.gitbook.cn/153b84c0-1c59-11e9-9a8e-f3b01b1ea9aa)

從上圖可以看出控制台列印出了很多資訊,包括我們的主機名稱、JDK 版本、作業系統等等。如果你成功看到這些資訊,說明你成功連接配接到  ZooKeeper 服務。

#### 檢視常用指令(help 指令)

help 指令檢視 zookeeper 常用指令

![help 指令](https://images.gitbook.cn/091db640-1c59-11e9-b5b7-abf0ec0c666a)

####  建立節點(create 指令)

通過 create 指令在根目錄建立了node1節點,與它關聯的字元串是"node1"

```shell
[zk: 127.0.0.1:2181(CONNECTED) 34] create /node1 “node1”
```
通過 create 指令在根目錄建立了node1節點,與它關聯的内容是數字 123

```shell
[zk: 127.0.0.1:2181(CONNECTED) 1] create /node1/node1.1 123
Created /node1/node1.1
```

#### 更新節點資料内容(set 指令)

```shell
[zk: 127.0.0.1:2181(CONNECTED) 11] set /node1 "set node1" 
```

#### 擷取節點的資料(get 指令)

get 指令可以擷取指定節點的資料内容和節點的狀态,可以看出我們通過set 指令已經将節點資料内容改為 "set node1"。

```shell
set node1
cZxid = 0x47
ctime = Sun Jan 20 10:22:59 CST 2019
mZxid = 0x4b
mtime = Sun Jan 20 10:41:10 CST 2019
pZxid = 0x4a
cversion = 1
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 9
numChildren = 1

```

#### 檢視某個目錄下的子節點(ls 指令)

通過 ls 指令檢視根目錄下的節點

```shell
[zk: 127.0.0.1:2181(CONNECTED) 37] ls /
[dubbo, zookeeper, node1]
```
通過 ls 指令檢視 node1 目錄下的節點

```shell
[zk: 127.0.0.1:2181(CONNECTED) 5] ls /node1
[node1.1]
```
zookeeper 中的 ls 指令和 linux 指令中的 ls 類似, 這個指令将列出絕對路徑path下的所有子節點資訊(列出1級,并不遞歸)

#### 檢視節點狀态(stat 指令)

通過 stat 指令檢視節點狀态

```shell
[zk: 127.0.0.1:2181(CONNECTED) 10] stat /node1
cZxid = 0x47
ctime = Sun Jan 20 10:22:59 CST 2019
mZxid = 0x47
mtime = Sun Jan 20 10:22:59 CST 2019
pZxid = 0x4a
cversion = 1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 11
numChildren = 1
```
上面顯示的一些資訊比如cversion、aclVersion、numChildren等等,我在上面 “ZNode(資料節點)的結構” 這部分已經介紹到。

#### 檢視節點資訊和狀态(ls2 指令)


ls2 指令更像是 ls 指令和 stat 指令的結合。ls2 指令傳回的資訊包括2部分:子節點清單 + 目前節點的stat資訊。

```shell
[zk: 127.0.0.1:2181(CONNECTED) 7] ls2 /node1
[node1.1]
cZxid = 0x47
ctime = Sun Jan 20 10:22:59 CST 2019
mZxid = 0x47
mtime = Sun Jan 20 10:22:59 CST 2019
pZxid = 0x4a
cversion = 1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 11
numChildren = 1

```

#### 删除節點(delete 指令)

這個指令很簡單,但是需要注意的一點是如果你要删除某一個節點,那麼這個節點必須無子節點才行。

```shell
[zk: 127.0.0.1:2181(CONNECTED) 3] delete /node1/node1.1
```

在後面我會介紹到 Java 用戶端 API的使用以及開源 Zookeeper 用戶端 ZkClient 和 Curator 的使用。


### 參考

- 《從Paxos到Zookeeper  分布式一緻性原理與實踐》      

繼續閱讀