zookeeper 知識點彙總

Zookeeper 是什麼

zookeeper 是軟件世界裏的管理者,被用來 提供分佈式環境的協調服務。zookeeper 是 yahoo 公司使用 java 語言開發的,是 Hadoop 項目中的子項目,基於 Google 的 Chubby 的開源實現,在 Hadoop,Hbase,Kafka 等技術中充當核心組件的角色。java

它的設計目標就是 將那些複雜而且容易出錯的分佈式一致性服務加以封裝,構成高效且可靠的服務,併爲用戶提供一系列簡單易用的接口node

Zookeeper 是一個經典的 分佈式數據一致性 解決方案,分佈式應用程序能夠基於它實現linux

  • 數據的發佈和訂閱
  • 負載均衡
  • 命名服務
  • 分佈式協調與通知
  • 集羣管理
  • 領導選舉
  • 分佈式鎖
  • 分佈式隊列

zookeeper 通常都以 集羣的方式 對外提供服務,一個集羣包含多個節點,每一個節點都對應一臺 Zookeeper 服務器,全部的節點共同對外提供服務。具體包括如下五大特性:shell

  1. 順序性
  2. 原子性
  3. 一致性
  4. 可靠性
  5. 實時性

Zookeeper 樹狀模型

Zookeeper 內部擁有樹狀的內存模型,與文件系統很是相似。apache

  • 在 Zookeeper 中將這些目錄與文件統稱爲 ZNode
  • 每一個 ZNode 都有對應的路徑及其包含的數據
  • ZNode 可由 Zookeeper 客戶端來建立
  • 當客戶端與服務端創建鏈接後,服務端將爲客戶端建立一個 Session (會話),客戶端對 ZNode 的全部操做均在這個會話中來完成

樹狀模型圖以下所示npm

ZNode 包含 4 類節點服務器

  • persistent 持久節點
  • persistent sequential 持久性順序節點
  • ephemeral 臨時性節點
  • ephemeral sequential 臨時性順序節點

Zookeeper 集羣結構

Zookeeper 設計了一個輕量級的協議 Zab (ZooKeeper Atomic Broadcast, Zookeeper 廣播協議)。Zab 協議分爲兩個階段:session

  • Leader Election 領導選舉架構

    Zookeeper 集羣啓動時,會選出一臺節點爲 Leader,而其餘節點均爲 Follower。當 Leader 出現故障時,會自動選舉出新的 Leader 節點,並讓全部節點恢復到一個正常的狀態。選舉結束後,會進入 原子廣播階段。

  • Atomic Broadcase 原子廣播

    該階段會同步 Leader 節點與 Follower 節點之間的數據,確保 Leader 與 Follower 節點具備相同的狀態。全部的寫操做都會發送到 Leader 節點,並經過廣播的方式同步到 Follower 節點。

一個 Zookeeper 集羣一般由一組節點組成,通常狀況下 3 ~ 5 個就能夠組成可用的 Zookeeper 集羣。

每一個節點都會在內存中維護當前的服務器狀態,並在每一個節點之間都會保持通訊,目的就是告訴其餘節點「本身還活着」。咱們通常會提供奇數個節點比較節省資源。此外, Zookeeper 客戶端能夠選擇集羣中任意一個節點來創建鏈接,而一旦客戶端與某個節點之間斷開聯繫,客戶端會自動鏈接到集羣的其餘節點。

如何使用 ZooKeeper

zookeeper 官方地址:http://zookeeper.apache.org/

zookeeper 使用 java 語言開發,使用前須要先安裝 jdk。下文是在 linux 環境下運行 zookeeper 的指導。

運行 Zookeeper

步驟1 修改 ZooKeeper 配置文件

Zookeeper 默認提供了一份名爲 zoo_sample.cfg 的示例配置文件,須要複製一下,並將其重命名爲 zoo.cfg 。配置文件的重要配置項以下

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/tmp/zookeeper
clientPort=2181

詳細解釋下以上配置項

  • tickTime 滴答時間,用於配置 Zookeeper 中最小時間單元的長度。單位爲 ms。默認值是 3000 ms。
  • initLimit 用於配置 Leader 節點等待 Follower 節點啓動並完成數據同步的時間, 默認值是 10 ,也就是 10 * tickTime
  • syncLimit 用來配置 Leader 節點與 Follower 節點之間心跳檢測的最大延時時間,默認值是 5,也就是 5 * tickTime
  • dataDir 用來配置 Zookeeper 服務器存儲快照文件的目錄,不建議將其指定到 /tmp 目錄下,由於該目錄下的全部文件可能被自動刪除。在 Zookeeper 環境中,將生成一個名爲 myid 的文件,用來存放 zk 集羣節點的 ID。
  • clientPort 用於配置當前 zk 服務器對外暴露的接口

步驟 2, 啓動 Zookeeper 服務器

啓動 Zookeeper 服務器很是簡單,只需執行 Zookeeper 提供的腳本程序便可。

bin/zkServer.sh start

執行上面腳本,默認會在後臺啓動 Zookeeper 服務器。

zkServer.sh 能夠傳入如下參數

  • start
  • start-foreground
  • stop
  • restart
  • status
  • upgrade
  • print-cmd

步驟 3, 驗證 Zookeeper 服務是否有效

bin/zkServer.sh status

還可使用 telnet 命令來驗證 ZooKeeper 服務是否有效

telnet 127.0.0.1 2181

zookeeper 當前處於 standard alone 模式下,通常狀況下咱們使用單機模式做爲開發環境,而使用集羣模式做爲生產環境。

搭建 Zookeeper 集羣環境

在本地搭建一個僞集羣模式的 Zookeeper 集羣環境(3 個節點)

修改 Zookeeper 配置文件

配置以下

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/usr/local/app-data/zookeeper/data
dataLogDir=/usr/local/zookeeper-3.4.6/logs
clientPort=2181
server.0=127.0.0.1:2888:3888
server.1=127.0.0.1:2889:3889
server.2=127.0.0.1:2890:3890

與單機模式的區別就在於添加了一組 server 配置,表示集羣中包含的三個節點,須要注意的是 server 配置須要知足必定的格式:

server.<id>=<ip>:<port1>:<port2>
  • id 表示節點編號,表示該節點在集羣中的惟一編號,取值在 0 ~ 255 之間。
    • 必須在 dataDir 目錄下建立一個名爲 myid 的文件,其內容是該節點的編號
  • ip 表示節點所在的 IP 地址,本機爲 127.0.0.1 或者是 localhost
  • port1 表示 Leader 節點與 Follower 節點心跳檢測與數據同步時使用的接口
  • port2 表示在領導選舉過程當中,用於投票通訊的端口

啓動 ZooKeeper 集羣

與單機模式的啓動方法相同,只需一次啓動全部的 ZooKeeper 節點便可啓動整個集羣

驗證 Zookeeper 集羣環境是否有效

和 standard alone 模式同樣,也能夠經過 zkServer.sh 腳本與 telnet 命令來查看每一個節點的狀態,此時會看到 Mode:leader 或者 Mode:follower 的信息,表示該節點是 Leader 仍是 Follower。

ZooKeeper 提供了一系列腳本程序,所有存放在 bin 目錄下,如

  • zkServer.sh 用於啓動 Zookeeper 服務器
  • zkCli.sh 用於鏈接 ZooKeeper 服務器的命令行客戶端
  • zkCleanup.sh 用於清理 ZooKeeper 的歷史數據,包括
    • 事務日誌文件
    • 快照數據文件
  • zkEnv.sh 用於設置 ZooKeeper 的環境變量

鏈接 zookeeper

使用 zkCli 鏈接 Zookeeper

鏈接 ZooKeeper 只須要執行如下腳本:

bin/zkCli.sh

若是想要鏈接遠程的 ZooKeeper, 則在 zkCli.sh 腳本中添加 -server 選項

bin/zkCli.sh -server <ip>:<port>

鏈接成功後,就能夠輸入相關的命令來操做 zookeeper 了。當輸入 help 命令後,將輸出 zookeeper 相關客戶端命令的使用幫助。

ZooKeeper -server host:port cmd args
        stat path [watch]
        set path data [version]
        ls path [watch]
        delquota [-n|-b] path
        ls2 path [watch]
        setAcl path acl
        setquota -n|-b val path
        history
        redo cmdno
        printwatches on|off
        delete path [version]
        sync path
        listquota path
        rmr path
        get path [watch]
        create [-s] [-e] path data acl
        addauth scheme auth
        quit
        getAcl path
        close
        connect host:port

列出子節點

命令格式以下

ls path [watch]

ls 命令中可設置一個 watch 參數,用於指定客戶端監視器,在 zooKeeper 中被稱爲 Watcher, Watcher 用於監控節點的狀態變化,默認狀況下可不帶有任何 Watcher。

[zk: localhost:2181(CONNECTED) 0] ls /
[zookeeper]

默認狀況下,根目錄中有一個名爲 zookeeper 的子節點,它做爲 Zookeeper 的保留節點,咱們通常不使用它。

此外,還可使用 ls2 命令以更加詳細的方式列出節點名稱及其相關屬性,命令格式以下

ls2 path [watch]

ls2 命令會輸出當前節點的基本信息

[zk: localhost:2181(CONNECTED) 2] ls2 /
[zookeeper]
cZxid = 0x0
ctime = Thu Jan 01 08:00:00 CST 1970
mZxid = 0x0
mtime = Thu Jan 01 08:00:00 CST 1970
pZxid = 0x0
cversion = -1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 1

在輸出信息中包含了大量的統計屬性:

  • cZxid 表示建立節點時的事務 ID (每一個客戶端請求都會造成一個事務)
  • ctime 表示建立節點的時間
  • mZxid 表示最後一次修改節點時的事務 ID
  • mtime 表示最後一次修改節點的時間
  • pZxid 表示最後一次修改父節點時的事務 ID
  • cversion 子節點的版本號
  • dataVersion 節點包含數據的版本號
  • aclVersion 表示節點的 ACL 權限版本號
  • ephemeralOwner 臨時節點的會話 ID
  • dataLength 表示節點包含數據內容的長度
  • numChildren 當前節點的子節點數

判斷節點是否存在

[zk: localhost:2181(CONNECTED) 8] stat /foo
Node does not exist: /foo

建立節點

使用 create 命令建立節點,命令格式以下

create [-s] [-e] path data acl

其中

  • -s 用於指定該節點是否爲順序節點,即 Sequential 節點

  • -e 選項:用於指定該節點是否爲臨時節點,即 Ephemeral 節點

  • acl 用於權限控制, Zookeeper 內部提供了一個強大的 ACL 訪問控制列表,默認狀況下不作任何權限控制

    [zk: localhost:2181(CONNECTED) 13] create -e /foo hello
    Created /foo

獲取節點數據

使用 get 命令獲取節點數據,命令格式以下

get path [watch]

能夠經過如下命令獲取 /foo 節點包含的數據

[zk: localhost:2181(CONNECTED) 14] get /foo
hello
cZxid = 0xa
ctime = Wed Jan 02 15:27:44 CST 2019
mZxid = 0xa
mtime = Wed Jan 02 15:27:44 CST 2019
pZxid = 0xa
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x1680d4a324f0002
dataLength = 5
numChildren = 0

更新節點數據

使用 set 命令更新節點數據,命令格式以下

set path data [version]

在更新節點數據時,可指定 version 參數,表示節點包含數據的版本號。若是不指定 version 參數,則表示更新節點數據的最新版本。

刪除節點

使用 delete 命令刪除節點,命令格式以下

delete path [version]

當節點沒有任何子節點時,才能刪除成功,不然將給出 "node not empty" 的提示,但能夠經過如下命令一次刪除該節點及其全部的子節點。

rmr path

使用 Node.js Client 鏈接 Zookeeper

Node.js 鏈接 Zookeeper 中比較好用的客戶端是 node-zookeeper-client

首先經過 NPM 來安裝這個模塊。

npm install node-zookeeper-client

先用一段代碼來展現鏈接 Zookeeper, 後面再基於該代碼,將 nodejs 針對 zookeeper 客戶端的操做執行一遍。

var zookeeper = require('node-zookeeper-client')

var CONNECTION_STRING = 'localhost:2181'

var OPTIONS = {
  sessionTimeout: 5000
}

var zk = zookeeper.createClient(CONNECTION_STRING, OPTIONS)

zk.on('connected', function() {
  console.log(zk);
  zk.close();
});

zk.connect();

若是 zk 能夠正常輸出,說明可成功鏈接 Zookeeper 服務器並創建了正常的會話, 下面全部的操做都在該會話中進行。Node.js 客戶端僅提供了異步方式,咱們不能經過同步方式來調用。

node-zookeeper-client 的官方文檔地址爲: https://www.npmjs.com/package/node-zookeeper-client

可執行的常見操做包括:

  • 列出子節點
  • 判斷節點是否存在
  • 建立節點
  • 獲取節點數據
  • 更新節點數據
  • 刪除節點

參考

  • 《架構探險—輕量級微服務架構》
相關文章
相關標籤/搜索