ZooKeeper入門。
作者:IT王小二
博客:https://itwxe.com
一、ZooKeeper簡介
ZooKeeper 致力於提供一個高性能、高可用,且具備嚴格的順序訪問控制能力的分布式協調服務,是雅虎公司創建,是 Google 的 Chubby 一個開源的實現,也是 Hadoop 和 Hbase 的重要組件。
1. ZooKeeper優點
- 簡單的數據結構:共享的樹形結構,類似文件系統,存儲於內存。
- 可以構建集群:避免單點故障,3-5 台機器就可以組成集群,超過半數正常工作就能對外提供服務。
- 順序訪問:對於每個讀請求,ZooKeeper 會分配一個全局唯一的遞增編號,利用這個特性可以實現高級協調服務。
- 高性能:基於內存操作,服務於非事務請求,適用於讀操作為主的業務場景,3 台 ZooKeeper 集群能達到 13w QPS。
2. 那些場景可以使用
- 數據發布訂閱
- 負載均衡
- 命名服務
- Master 選舉
- 集群管理
- 配置管理
- 分布式隊列
- 分布式鎖
二、ZooKeeper安裝
ZooKeeper的安裝配置不論是單機安裝還是集群(或者集群偽分布)都是非常的簡單。
首先准備工作
- Linux 需要安裝配置jdk環境。
- 從 ZooKeeper官網 下載 ZooKeeper 安裝包,然后上傳至Linux,我上傳在
/usr/local
目錄下。
下面的內容都是基於 CentOS7 安裝ZooKeeper(3.4.12)。
1. 單機安裝
1、解壓壓縮包。
tar -zxvf zookeeper-3.4.12.tar.gz
2、進入解壓的目錄,將配置文件zoo_sample.cfg
復制一份為zoo.cfg
,因為 ZooKeeper 啟動時默認配置文件為zoo.cfg
,當然你也可以指定配置文件 zoo_sample.cfg
啟動(命令:./zkServer.sh start ../conf/zoo_sample.cfg
)。
cd zookeeper-3.4.12/conf
cp zoo_sample.cfg zoo.cfg
3、修改 zoo_sample.cfg 配置文件的 dataDir 屬性,這里存放了 ZooKeeper 的快照文件,根據自己的需求修改,如果定義的目錄不存在需要先創建出來。
vim zoo.cfg
dataDir=/usr/local/zookeeper-3.4.12/data
4、進入解壓目錄 zookeeper-3.4.12 下的 bin 目錄,啟動 ZooKeeper,相關命令如下:
啟動命令:./zkServer.sh start
停止命令:./zkServer.sh stop
重啟命令:./zkServer.sh restart
狀態查看命令:./zkServer.sh status
5、啟動后,可以查看一下狀態是否啟動成功,然后使用命令行進行登錄操作,之后就可以嘗試使用 ZooKeeper 的命令行了,命令操作再后面介紹。
./zkCli.sh -server 192.168.182.130:2181
2. 集群安裝
集群偽分布就是在一台服務器上面部署多個ZooKeeper,這里就不使用 集群偽分布 來示例了,之前 Redis 有使用過集群偽分布,集群偽分布就是通過配置文件端口號區別多個ZooKeeper,集群最好以奇數個為佳。
過程如下
1、不使用集群偽分布,那么首先准備好三台Linux服務器,我這里使用了三個虛擬機CentOS7,ip分別為:192.168.182.130、192.168.182.131、192.168.182.132,同時開放 2888 和 3888 這兩個端口訪問,不然集群無法相互通信,查看狀態一直為 ERROR。
2、然后還是和單機安裝一樣,解壓安裝文件,復制配置文件,修改配置文件,不過配置文件還需要增加一個集群配置,貼出我的配置,其中:2888:集群內機器通訊使用(Leader監聽此端口);3888:選舉leader使用。
# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
dataDir=/usr/local/zookeeper-3.4.12/data
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
# 增加的集群配置
server.0=192.168.182.130:2888:3888
server.1=192.168.182.131:2888:3888
server.2=192.168.182.132:2888:3888
3、配置好 192.168.182.130 這台服務器的配置文件之后,還需要做一件事情,在配置的 dataDir=/usr/local/zookeeper-3.4.12/data
目錄下生成一個myid文件,分別對應上面配置中的server.0、server.1、server.2,例如 192.168.182.130 對應的就是 0 。
echo 0 > myid
4、將 zookeeper-3.4.12
這個目錄使用 scp
命令遠程復制到 192.168.182.131 和 192.168.182.132這兩個服務器的 /usr/local
目錄下,遠程復制碰到登錄密碼輸入即可,當然,你也可以使用其他工具復制。
scp -r /usr/local/zookeeper-3.4.12 root@192.168.182.131:/usr/local
scp -r /usr/local/zookeeper-3.4.12 root@192.168.182.132:/usr/local
5、前面提到 192.168.182.130 對應配置文件中的 0,那么 192.168.182.131 對應的就是 1,192.168.182.132 對應的就是2,所以還需要在這兩台服務器上 分別更改 myid 文件內容。
echo 1 > myid
echo 2 > myid
6、最后分別啟動每個服務器上的 ZooKeeper 就可以了,分別啟動后可以查看一下三台服務器節點的狀態,如果顯示 Mode: follower
或者 Mode: leader
則代表集群成功,可以使用以下命令行工具查看效果。
3. ZooKeeper安裝目錄結構
- bin:存放系統腳本
- conf:存放配置文件
- contrib:附加功能支持
- dist-maven:maven 倉庫文件
- docs:文檔
- lib:依賴的第三方庫
- recipes:經典場景樣例代碼
- src:源碼
其中 bin 和 conf 是非常重要的兩個目錄,平時也是經常使用的。
bin目錄
常用的兩個:zkServer.sh 為服務端,zkCli 為命令行客戶端。
conf目錄
主要是配置文件的參數,其中幾個比較重要的如下:
- clientPort:訪問端口,即應用對外服務的端口。
- dataDir:用於存放內存數據庫快照的文件夾,同時用於集群的 myid 文件也存在這個文件夾里(注意:一個配置文件只能包含一個 dataDir 字樣,即使它被注釋掉了),新安裝這文件夾里面是沒有文件的,可以通過 snapCount 參數配置產生快照的時機。
- snapCount:每進行 snapCount 次事務日志輸出后,觸發一次快照(snapshot), 此時,ZooKeeper 會生成一個
snapshot.*
文件,同時創建一個新的事務日志文件log.*
,默認是100000(真正的代碼實現中,會進行一定的隨機數處理,以避免所有服務器在同一時間進行快照而影響性能)(Java system property:zookeeper.snapCount )。 - dataLogDir:用於單獨設置 transaction log 的目錄,transaction log 分離可以避免和普通 log 還有快照的競爭。
- tickTime:心跳時間,為了確保連接存在的,以毫秒為單位,最小超時時間為兩個心跳時間。
- initLimit:多少個心跳時間內,允許其他 server 連接並初始化數據,如果 ZooKeeper 管理的數據較大,則應相應增大這個值。
- syncLimit:多少個 tickTime 內,允許 follower 同步,如果 follower 落后太多,則會被丟棄。
三、ZooKeeper特性
1. 會話
客戶端與服務端的一次會話連接,本質是 TCP 長連接,通過會話可以進行心跳檢測和數據傳輸。
會話狀態
ZooKeeper 客戶端和服務端成功連接后,就創建了一次會話,ZooKeeper 會話在整個運行期間的生命周期中,會在不同的會話狀態之間切換,這些狀態包括:CONNECTING、CONNECTED、RECONNECTING、RECONNECTED、CLOSE。
一旦客戶端開始創建 Zookeeper 對象,那么客戶端狀態就會變成 CONNECTING 狀態,同時客戶端開始嘗試連接服務端,連接成功后,客戶端狀態變為 CONNECTED,通常情況下,由於斷網或其他原因,客戶端與服務端之間會出現斷開情況,一旦碰到這種情況,Zookeeper 客戶端會自動進行重連服務,同時客戶端狀態再次變成 CONNCTING,直到重新連上服務端后,狀態又變為 CONNECTED,在通常情況下,客戶端的狀態總是介於 CONNECTING 和 CONNECTED 之間。但是,如果出現諸如會話超時、權限檢查或是客戶端主動退出程序等情況,客戶端的狀態就會直接變更為 CLOSE 狀態。
2. 數據模型
ZooKeeper 的視圖結構和 Unix 文件系統類似,其中每個節點稱為“數據節點”或 ZNode, 每個 znode 可以存儲數據,還可以掛載子節點,因此可以稱之為“樹”,需要注意的是,每一個 znode 都必須有值,如果沒有值,節點是不能創建成功的。
- 在 Zookeeper 中,znode 是一個跟 Unix 文件系統路徑相似的節點,可以往這個節點存儲或獲取數據。
- 通過客戶端可對 znode 進行增刪改查的操作,還可以注冊 watcher 監控 znode 的變化。
3. 節點類型
zNode有兩種節點類型:持久節點(persistent)、臨時節點(ephemeral)
第一種:持久節點創建:不須其他參數,value可以為任意值,持久節點客戶端斷開連接后不會刪除。
create /SunnyBear value
第二種:臨時節點創建:加上 -e 參數即代表創建臨時節點,客戶端斷開連接后會刪除。
create -e /testSunnyBear ephemeralNodeTest
zNode節點有四種形式的目錄節點:持節節點、持久順序節點、臨時節點、臨時順序節點
持久節點 和 臨時節點 前面已經說了,那么來看下 持久順序節點 和 臨時順序節點,創建時加上參數 -s 則代表加上了順序,例如分別創建 持久順序節點 和 臨時順序節點。
create -s /SunnyBear2 tests
# 返回了Created /SunnyBear20000000008
create -e -s /testSunnyBear ephemeralNodeTest
# 返回了Created /testSunnyBear0000000009
從上面的結果可以看到,順就節點即在創建的節點名稱后面加上了序號,並且同時需要注意的是,create 命令如果不是創建順序節點,如果節點名稱已經存在是無法創建的,會報錯Node already exists: /SunnyBear
,還有臨時節點不允許有子節點。
4. ZooKeeper節點狀態屬性
屬性 | 數據結構 | 描述 |
---|---|---|
cZxid | long | 節點被創建的Zxid值 |
ctime | long | 節點被創建的時間 |
mZxid | long | 節點被修改的Zxid值 |
mtime | long | 節點被修改的時間 |
pZxid | long | 子節點最后一次被修改時的Zxid值 |
cversion | long | 子節點的版本號 |
dataVersion | long | 節點修改的版本號 |
aclVersion | long | 節點的ACL被修改的版本號 |
ephemeralOwner | long | 如果此節點為臨時節點,那么它的值為這個節點持有者的會話ID,否則,它的值為0 |
dataLength | int | 節點數據域的長度 |
numChildren | int | 節點擁有的子節點的長度 |
- 其中 Zxid 為 事務id,可以識別出請求的全局順序。
- 基於 CAS 理論保證分布式數據原子性操作。
5. ACL保障數據的安全
ACL 機制,表示為 scheme🆔permissions 格式,第一個字段表示采用哪一種機制,第二個 id 表示用戶,permissions 表示相關權限(如只讀,讀寫,管理等),詳細的命令使用在后面介紹。
四、命令行
1. 服務端常用命令
啟動命令:./zkServer.sh start
停止命令:./zkServer.sh stop
重啟命令:./zkServer.sh restart
狀態查看命令:./zkServer.sh status
2. 客戶端常用命令
使用 ./zkCli.sh ip:端口
命令連接到 ZooKeeper,連接成功之后就可以使用下面的命令了,前面也提到了一些命令。
# 查看當前 ZooKeeper 中根目錄下的子節點信息
ls /
# 查看當前 ZooKeeper 中根目錄下子節點信息,並能看到更新次數等數據
ls2 /
# 創建節點,這個之前已經提到過了,其中-e代表臨時節點,-s代表為順序節點
create [-e] [-s] zNodeName zNodeValue
# 獲取創建節點的信息
get /zNodeName
# 修改節點內容,這個和redis不同,如果key不存在,那么會報錯
set /zNodeName zNodeValue
# 刪除節點,如果存在子節點刪除失敗
delte /zNodeName
# 遞歸刪除,子節點同時刪除
rmr /zNodeName
# 退出客戶端
quit
# 幫助命令
help
3. ACL命令常用命令
之前提到了ACL命令為 scheme🆔permissions 格式,那么分別看下這三段代表什么。
- schema:代表授權策略
- id:代表用戶
- permission:代表權限
scheme
scheme有四種方式:
- world:默認方式,所有人都可以訪問
- auth:代表已經認證通過的用戶
- digest:即用戶名:密碼這種方式認證,這也是業務系統中最常用的
- ip:使用ip地址認證
id
和 scheme 一一對應,他也有四種:其中 auth 為明文,digest 為密文
- world -> anyone
- auth -> username:password
- digest -> username:BASE64(SHA1(password))
- ip -> 客戶端ip地址
permission
c(CREATE)、d(DELETE)、r(READ)、w(WRITE)、a(ADMIN)這幾個權限,對應增,刪,查,改,管理權限,簡稱cdrwa
- c:創建子節點的權限
- d:刪除子節點的權限
- r:讀取節點數據的權限
- w:修改節點數據的權限
- a: 給子節點授權的管理權限
具體命令
# 獲取子節點的ACL信息
getAcl /zNodeName
# 設置子界面ACL信息,例如:
# 設置所有人都可以訪問testDir節點,但是卻沒有刪除權限
setAcl /testDir world:anyone:crwa
# 設置auth方式,先增加用戶再賦予權限,例如對/testDir目錄下的/testAcl1進行操作
create /testDir/testAcl1 testAcl1
addauth digest user1:123456
setAcl /testDir/testAcl1 auth:user1:123456:crwa
# 設置digest方式,這個和auth的區別就是明文密碼和密文密碼的區別,不適用密文密碼會設置失敗,所以需要獲取密文密碼
# 通過shell命令獲取密文密碼
java -Djava.ext.dirs=/usr/local/zookeeper-3.4.12/lib -cp /usr/local/zookeeper-3.4.12/zookeeper-3.4.12.jar org.apache.zookeeper.server.auth.DigestAuthenticationProvider user2:123456
# 得到結果
user2:123456->user2:hZG2W+NR7DCvADzOkGR6JGLqoTY=
# 接下來就是基本操作了,使用zkCli客戶端登錄
create /testDir/testAcl2 testAcl2
addauth digest user2:123456
setAcl /testDir/testAcl2 digest:user2:hZG2W+NR7DCvADzOkGR6JGLqoTY=:crw
# 設置ip方式
create /testDir/testAcl3 testAcl3
set /testDir/testAcl3 ip:192.168.31.6:cdrwa
設置之后就可以使用命令來測試以下權限是否設置成功了,如果是 auth 和 digest的那么需要登錄來獲取權限,quit退出連接重新連接ZooKeeper,然后執行下面命令就可測試了。
addauth digest user1:123456
五、ZooKeeper日志
前面 conf 配置中提交到 dataDir 和 dataLogDir
- dataDir:ZooKeeper 的數據目錄,主要目的是存儲內存數據庫序列化后的快照路徑,可以通過 snapCount 參數配置產生快照的時機,默認是100000,但是實際源碼中會使用 50000 + random(50000) 作為實際產生快照的操作次數,避免多個節點同時產生快照,影響性能。如果沒有配置事務日志(即dataLogDir配置項)的路徑,那么 ZooKeeper 的事務日志也存放在數據目錄中。
- dataLogDir:指定事務日志的存放目錄。事務日志對ZooKeeper的影響非常大,強烈建議事務日志目錄和數據目錄分開,不要將事務日志記錄在數據目錄(主要用來存放內存數據庫快照)下。
快照即類似於 Redis 中的RDB,每 50000 + random(50000) 次記錄操作就生成快照;
事務日志則類似於 Redis 中的AOF,記錄着每一條操作命令。
查看快照和事務日志文件內容命令
需要注意的是,下面命令的分隔符在window上是;
,在Linux上面是:
,同時還需要注意 jar版本號 和 文件目錄位置,修改為自己的。
查看快照:
java -cp ../../zookeeper-3.4.12.jar:../../lib/slf4j-api-1.7.25.jar org.apache.zookeeper.server.SnapshotFormatter snapshot.xxx
查看事務日志:
java -cp ../../zookeeper-3.4.12.jar:../../lib/slf4j-api-1.7.25.jar org.apache.zookeeper.server.LogFormatter log.xxx
都讀到這里了,來個 點贊、評論、關注、收藏 吧!