安裝配置ZooKeeper及基本用法

  • 2019 年 10 月 7 日
  • 筆記

要想學習分佈式應用,ZooKeeper是一個繞不過去的基礎系統。它為大型分佈式計算提供開源的分佈式配置服務、同步服務和命名註冊。

今天先介紹系統的安裝和基本使用,後續會推一些基本的Java使用代碼。

1 安裝配置ZooKeeper

https://www.apache.org/dyn/closer.cgi/zookeeper/,下載最新的ZooKeeper程序,當前最新版本是3.5.5,要求JDK在1.8以上。

1.1 基本安裝

將下載的apache-zookeeper-3.5.5-bin.tar.gz文件使用命令tar -xzvf 解壓到 /usr/java 目錄,並將原目錄名修改為zookeeper-3.5.5。

進入zookeeper-3.5.5目錄並創建兩個子目錄 data 和logs。

# mkdir data logs# echo 創建一個唯一的zookeeper實例號,我是用IP最後一個位元組# cd data# vim myid // 輸入 128 後保存退出 128# echo 複製 zoo_sample.cfg 為 zoo.cfg# cp zoo_sample.cfg zoo.cfg# 修改參數 dataDir# vim zoo.cfgdataDir=/var/lib/zookeeper

然後修改 /etc/profile,增加修改相應的環境變量

# vim /etc/profileexport PGDATA=/usr/java/postgres/dataZOOKEEPER_HOME=/usr/java/zookeeper-3.5.5PATH=$ZOOKEEPER_HOME/bin:$PATHexport ZOOKEEPER_HOME PATH# zkServer.sh start //啟動服務# zkServer.sh status //查看服務狀態# zkServer.sh stop //停止服務

Zookeeper使用的默認端口是2181,可以在conf/zoo.cfg中修改這個端口號。安裝完成後,需要在防火牆開啟端口

# firewall-cmd –zone=public –add-port=2181/tcp –permanent# firewall-cmd –reload

1.2 ZooKeeper安裝為服務

創建自動啟動的腳本

# cd /etc/rc.d/init.d# touch zookeeper# chmod +x zookeeper# vim zookeeper#!/bin/bash#chkconfig:2345 10 90#description:service zookeeper #set java environmentJAVA_HOME=/usr/java/jdk8u222-b10JRE_HOME=/usr/java/jdk8u222-b10/jreCLASS_PATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/libPATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/binexport JAVA_HOME JRE_HOME CLASS_PATH PATH export PGDATA=/usr/java/postgres/dataZOOKEEPER_HOME=/usr/java/zookeeper-3.5.5PATH=$ZOOKEEPER_HOME/bin:$PATH export PATH ZOOKEEPER_HOME su root ${ZOOKEEPER_HOME}/bin/zkServer.sh "$1" // 添加到啟動腳本# chkconfig –add zookeeper // 手工啟動# service start zookeeper

1.3 控制台使用zookeeper

命令行連接到zookeeper

# zhCli.sh -server 127.0.0.1:2181

嘗試輸入help查看可用的命令,列出了命令,發現其實沒有help命令。

輸入ls,查看根目錄下有哪些節點

嘗試創建一個新的節點,並設置一個字符串,然後使用命令get查看已經創建的節點。

嘗試為/hello重新賦值

賦值命令執行後,控制台收到了一條通知事件:/hello值已經被修改。重新查看這個值,發現它的版本(dataVersion)已經從0變為1。

再執行刪除命令,刪掉這個節點

1.4 Windows客戶端程序

在Windows上,可以安裝zkui這個ZooKeeper的客戶端,下載網址:https://github.com/echoma/zkui/wiki/Download 。

下載解壓後,直接運行 zkui.exe,彈出來連接頁面。

在Host部分輸入ZooKeeper的地址和端口,點擊Login按鈕後,左邊窗口列出Root下的所有zNode。使用比較簡單,自己摸索幾分鐘就都會了。

1.5 ZooKeeper複製模式

在評估、開發、測試環境,使用一台ZooKeeper就可以了,但在生產環境應該配置為多點複製模式。同一個應用多台服務器複製部署的情況,術語叫 quorum,所有的服務器使用相同的配置文件。

複製模式部署,最少需要三台服務器,並且服務器的總數最好是奇數。複製模式部署,配置文件 conf/zoo.cfg同單點模式差不多,有一些不同,如:

dataDir=/var/lib/zookeeperclientPort=2181tickTime=2000initLimit=5syncLimit=2server.128=zoo1:2888:3888server.129=zoo2:2888:3888server.130=zoo3:2888:3888

在配置文件中,initLimit是集群中ZooKeeper Server連接到leader的超時時間;syncLimit是服務器的超時時間。這兩個參數,使用的時間單位都是tickTime,initLimit值為5,最終代表的是10秒;syncLimit值為2,最終代表的是4秒。

列表server.X構成了整個ZooKeeper服務,當服務啟動的時候,會讀取data/myid文件,獲取自己的編號。

在server後面有兩個端口號:"2888"和"3888"。ZooKeeper服務器之間使用這兩個端口進行通信。如果使用同一台機器安裝多個ZooKeeper實例搭建集群,每個實例應該使用不同的端口,如:2888:3888/2889:3889/2890:3890;另外,每個實例的dataDir和clientPort也應該不同。

2 編程使用ZooKeeper

2.1 數據模型

ZooKeeper使用層級命名空間,類似一個分佈式文件系統。區別在於目錄節點也可以綁定數據,類似於一個文件系統,一個文件同時也是一個目錄。ZooKeeper不支持相對路徑。Unicode字符都可以出現在名稱中,除了下面的一些特例:

  • 不能使用null字符(u0000)
  • 下面的字符不能正常顯示,也不能使用:u0001-u001F和u007F和u009F
  • 下面的字符不允許:ud800 – uF8FF, uFFF0 – uFFFF
  • .可以是名稱的一部分,但不能獨立使用 . 和 ..,下面的名稱不合法:"/a/b/./c"或"/a/b/../c"
  • "zookeeper" 是保留字

2.2 ZNodes

在ZooKeeper樹中,每一個節點就是一個znode。Znode包括一個stat結構,含數據修改的版本號,以及acl版本號,時間戳。每次一個znode節點的數據發生變化,版本號都會增加。當客戶端讀取數據時,也會把數據的版本號一併取回去。當客戶端嘗試修改或刪除一個znode時,需要提供嘗試修改節點的版本號。如果提供的版本號同系統中當前的版本號不一致,更新失敗。(類似於數據庫的樂觀鎖實現)

ZNodes是程序訪問的實體,有幾個需要了解的特性:

  • Watches:客戶端可以在znode上設置監聽。znode數據發生變化時會觸發watch,然後清除watch。當watch觸發時,ZooKeeper會向客戶端發送一個通知。
  • 數據訪問:znode上的數據,讀寫都是原子性的。讀,是將整個znode的所有數據都讀出來;寫,會替換znode的所有數據。每個znode有訪問控制列表(Access Control List-ACL),用於限制誰可以訪問。ZooKeeper不是設計用於保存普通數據或大數據存儲,一般用於保存配置文件、狀態信息等。數據通常比較小,一般以KB為單位。ZooKeeper的客戶端也限制數據不能超過1M。如果業務需要保存大數據,可以將數據保存到大的存儲系統如NFS/HDFS等,並將其指針保存到ZooKeeper中。
  • 臨時節點:ZooKeeper可以保存一些短生命周期的節點,比如會話信息,當會話失效時這些節點會被刪除。因為這個特性,臨時節點不允許有子節點。
  • 順序節點(唯一命名):創建一個節點時,可以要求ZooKeeper在路徑後面添加自增的數字。格式為%010d,是10個數字,如0000000001。最大數值是2147483647,超過後會溢出,變成-2147483648。
  • 容器節點(3.5.3增加):用於一些特定的場景如leader、lock。當容器中的最後一個節點被刪除後,容器變成候補(candidate)狀態,服務器會擇機自行刪除。當你在容器節點中創建子節點時,可能會得到KeeperException.NoNodeException;因此創建子節點時應該catch這個異常,如果發生了則重新創建容器節點。
  • TTL節點(3.5.3增加):創建PERSISTENT或PERSISTENT_SEQUENTIAL節點時,可以以毫秒為單位設置TTL時間,如果在TTL時間之內沒有修改數據,也沒有創建子節點,服務器會在超時後擇機刪除這個節點。注意:這個參數缺省是關閉的,需要在系統參數中啟用。

2.3 ZooKeeper中的時間

通過多種方式跟蹤時間

  • Zxid:ZooKeeper的每次修改,都會收到zxid格式的時間戳。這表示在ZooKeeper上修改的順序。如果zxid1<zxid2,說明zxid2後發生。
  • 版本號(Version numbers):一個節點的每次修改,該節點的版本號都會增加。有三個版本號:version (節點數據的修改次數), cversion (子節點數據的修改次數), aversion (節點ACL修改的次數).
  • Ticks:使用ZooKeeper複製模式時,服務器使用ticks來定義事件的時間如:上載狀態、會話超時時間、服務器之間的連接超時時間等。
  • Real time:ZooKeeper不使用真實時間。

2.4 ZooKeeper Stat結構

節點的Stat結構有如下屬性

  • czxid:節點創建時的zxid
  • mzxid:節點最後一次修改時的zxid
  • pzxid:子節點最後一次修改時的zxid
  • ctime:節點創建時的時間戳,毫秒
  • mtime:節點最後一次修改時的時間戳,毫秒
  • version:節點數據的修改次數
  • cversion:子節點數據的修改次數
  • aversion:節點ACL的修改次數
  • ephemeralOwner:如果這是臨時節點,保存節點擁有者的session id;否則為0
  • dataLength:節點數據長度
  • numChildren:子節點個數

2.5 ZooKeeper Watches

ZooKeeper的所有讀操作getData()、getChildren()和exists()都有一個備選參數:設置watch。ZooKeeper Watch的定義:是一次性的觸發器,當數據發生變化時,向設置了watch的客戶端發送消息。有三個關鍵點:

  • 一次性觸發器:當數據變化時,向客戶端發送watch事件。例如:使用命令 getData(「/hello」, true)讀取數據,當/hello被修改或刪除時,客戶端都會收到事件。當數據再次發生變化時,客戶端就不會收到事件了。
  • 推送到客戶端:ZooKeeper設計用於保證客戶端能夠按照特定的順序收到推送事件。
  • Watch的數據對象:有兩種類型的watch,數據watch和子節點watch。getData()和exists()設置數據warch;getChildren()設置子節點watch。

2.6 ZooKeeper訪問控制

ZooKeeper使用ACL控制節點的讀寫權限。父子節點的讀寫權限是獨立的,不遞歸。

ZooKeeper支持的幾種權限:

  • CREATE: 可以創建子節點
  • READ: 可以讀取節點數據並列出子節點
  • WRITE: 可以修改節點數據
  • DELETE: 可以刪除子節點
  • ADMIN: 可以設置權限

ZooKeeper內置的授權對象

  • world:所有用戶
  • auth:當前用戶
  • digest:使用 username:password指定的用戶,密碼會做MD5摘要
  • ip:使用客戶端IP地址,格式是 addr/bits
  • x509:使用X500認證信息,用戶名