Zookeeper(1)-安裝與基礎使用

李小龍他哥發表於2022-03-11

Zookeeper

服務端

工作機制

Zookeeper從設計模式角度來理解:是一個基於觀察者模式設計的分散式服務管理框架,它負責儲存和管理大家都關心的資料,然後接受觀察者的註冊,一旦這些資料的狀態發生變化,Zookeeper 就將負責通知已經在Zookeeper上註冊的那些觀察者做出相應的反應。

Zookeeper = 檔案系統 + 通知機制

特點

  1. Zookeeper:一個領導者(Leader),多個跟隨者(Follower)組成的叢集。
  2. 叢集中只要有半數以上節點存活,Zookeeper叢集就能正常服務。所以Zookeeper適合安裝奇數臺伺服器
  3. 全域性資料一致:每個Server儲存一份相同的資料副本,Client無論連線到哪個Server,資料都是一致的。
  4. 更新請求順序執行,來自同一個Client的更新請求按其傳送順序依次執行。
  5. 資料更新原子性,一次資料更新要麼成功,要麼失敗。
  6. 實時性,在一定時間範圍內,Client能讀到最新資料。

資料結構

ZooKeeper 資料模型的結構與 Unix 檔案系統很類似,整體上可以看作是一棵樹,每個 節點稱做一個 ZNode。每一個 ZNode 預設能夠儲存 1MB 的資料,每個 ZNode 都可以通過其路徑唯一標識

圖片

應用場景

提供的服務包括:統一命名服務、統一配置管理、統一叢集管理、伺服器節點動態上下線、軟負載均衡等。

統一命名服務

在分散式環境下,經常需要對應用/服 務進行統一命名,便於識別。

例如:IP不容易記住,而域名容易記住。

統一配置管理

  1. 分散式環境下,配置檔案同步:

    1. 一般要求一個叢集中,所有節點的配置資訊是一致的,比如 Kafka 叢集。

    2. 對配置檔案修改後,希望能夠快速同步到各個 節點上。

  2. 配置管理可交由 Zookeeper 實現:

    1. 可將配置資訊寫入ZooKeeper上的一個Znode。
    2. 各個客戶端伺服器監聽這個Znode。
    3. 一 旦Znode中的資料被修改,ZooKeeper將通知各個客戶端伺服器。

統一叢集管理

  1. 分散式環境中,實時掌握每個節點的狀態是必要的。
    1. 可根據節點實時狀態做出一些調整。
  2. ZooKeeper可以實現實時監控節點狀態變化
    1. 可將節點資訊寫入ZooKeeper上的一個ZNode。
    2. 監聽這個ZNode可獲取它的實時狀態變化。

Zookeeper 安裝

下載ZooKeeper:http://pan.baidu.com/s/1pJlwbR9

解壓:tar -zxvf zookeeper-3.4.5.tar.gz 重新命名:mv zookeeper-3.4.5 zk

Zookeeper 引數詳解

# 通訊心跳時間,Zookeeper伺服器與客戶端心跳時間,單位毫秒
tickTime=2000
# LF初始通訊時限
# Leader 和 Follower 初始連線時能容忍的最多心跳數(tickTime 的數量)
initLimit=10
# LF 同步通訊時限
# Leader 和 Follower 之間通訊時間如果超過 syncLimit * tickTime,leader 認為 Follower 死掉,從伺服器列表中刪除 Follower
syncLimit=5
# 儲存 Zookeeper 中的資料
# 預設存放在 tmp 目錄,容易被 Linux 系統定期刪除,所以一般不用預設的 tmp 目錄
dataDir=/opt/module/zookeeper-3.5.7/zkData
# 客戶端連線埠,通常不做修改
clientPort=2181

Zookeeper 叢集配置

配置

新增伺服器編號的配置檔案,在配置檔案中 dataDir=/opt/module/zookeeper-3.5.7/zkData 下建立 myid 檔案,在檔案中新增與 server 對應的編號

修改配置檔案,在 bin/zoo_sample.cfg 後面追加對應主機的配置資訊,每一臺主機對應的配置檔案都要進行修改。

server.2=192.168.3.19:2888:3888
server.3=192.168.3.33:2888:3888
server.4=192.168.3.34:2888:3888

配置檔案詳解

server.A=B:C:D

A:是一個資料,表示這是幾號伺服器,對應每臺伺服器建立的 myid 裡面的數字;Zookeeper 啟動時讀取此檔案,拿到裡面的資料與 zoo.cfg 裡面的配置資訊比 較從而判斷到底是哪個 server

B:對應的伺服器地址;

C:是這個伺服器 Follower 與叢集中的 Leader 伺服器交換資訊的埠;

D:是萬一叢集中的 Leader 伺服器掛了,需要一個埠來重新進行選舉,選出一個新的 Leader,而這個埠就是用來執行選舉時伺服器相互通訊的埠。

執行

分別啟動對應的 Zookeeper,我這邊配置的是三臺Zookeeper伺服器;

啟動第一臺的 Zookeeper 的狀態:

[root@localhost zookeeper-3.5.7]# sh ./bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Error contacting service. It is probably not running.

此時提示 Error contacting service. It is probably not running. 因為現在還只啟動一臺 Zookeeper,不滿足 半數以上 的節點存活,所以現在不能正常提供服務。

後面依次啟動對應的 Zookeeper 服務。

第二臺啟動與對應的狀態

[root@localhost zookeeper-3.5.7]# sh ./bin/zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED

[root@localhost zookeeper-3.5.7]# sh ./bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: leader

第三臺啟動與對應的狀態

[root@localhost zookeeper-3.5.7]# sh ./bin/zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED

[root@localhost zookeeper-3.5.7]# sh ./bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: follower

第一臺伺服器的狀態

[root@localhost zookeeper-3.5.7]# sh ./bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: follower

到這裡 Zookeeper 叢集的配置與啟動就搞定了。

Zookeeper 的選舉機制

第一次啟動的時候

以我上面的三個 Zookeeper 伺服器叢集為例:

  1. 伺服器1啟動,發起一次選舉。伺服器1投自己一票。此時伺服器1票數一票,不夠半數以上(2票),選舉無法完成,伺服器1狀態保持為 LOOKING;

    b4RjZ6.png

  2. 伺服器2啟動,再發起一次選舉。伺服器1和2分別投自己一票並交換選票資訊:此時伺服器1發現伺服器2的myid比自己目前投票推舉的(伺服器1) 大,更改選票為推舉伺服器2。此時伺服器1票數0票,伺服器2票數2票,此時伺服器2的票數已經超過半數,伺服器2當選Leader。伺服器1更改狀態為FOLLOWING,伺服器2更改狀態為LEADING;

    b4WQQs.png

  3. 伺服器3啟動,發起一次選舉。此時伺服器1,2已經不是LOOKING狀態,不會更改選票資訊。交換選票資訊結果:伺服器2為2票,伺服器3為 1票。此時伺服器3服從多數,更改選票資訊為伺服器2,並更改狀態為FOLLOWING;

    b4WBO1.png

非第一次啟動的時候

這裡首先還要先講出關於Zookeeper叢集Client端的一些其他概念:

b4fKAK.md.png

SID伺服器ID。用來唯一標識一臺 ZooKeeper叢集中的機器,每臺機器不能重複,和 myid 一致。

ZXID事務idZXID是一個事務ID,用來標識一次伺服器狀態的變更。在某一時刻, 叢集中的每臺機器的ZXID值不一定完全一 致,這和 ZooKeeper 伺服器對於客戶端 更新請求 的處理邏輯有關。

Epoch每個Leader任期的代號。沒有Leader時同一輪投票過程中的邏輯時鐘值是相同的。每投完一次票這個資料就會增加。

Zookeeper 會發生選舉的場景
  • 伺服器初始化啟動(上面描述了)
  • 伺服器執行期間無法和 Leader 保持連線
一臺伺服器進入選舉的兩種狀態
  1. 叢集中本來就已經存在一個 Leader:

    機器試圖去選舉Leader時,會被告知當前伺服器的Leader資訊,對於該機器來說,僅僅需要和Leader機器建立連 接,並進行狀態同步即可。

  2. 叢集中確實不存在 Leader

    假設ZooKeeper由5臺伺服器組成,SID分別為1、2、3、4、5,ZXID分別為8、8、8、7、7,並且此時SID為3的伺服器是Leader。某一時刻, 3和5伺服器出現故障,因此開始進行Leader選舉。

    1(EPOCH,ZXID,SID ) 2(EPOCH,ZXID,SID ) 4(EPOCH,ZXID,SID )
    SID 為 1、2、4 的機器投票情況 (1,8,1) (1,8,2) (1,7,4)

    選舉規則:

    1. EPOCH大的直接勝出;
    2. EPOCH相同,事務id大的勝出
    3. 事務id相同,伺服器id大的勝出;

叢集啟動指令碼

#!/bin/bash

case $1 in
"start"){
	for i in 192.168.3.19 192.168.3.33 192.168.3.34
	do
		echo ----------- zookeeper $i 啟動 -------------
		ssh $i "/opt/module/zookeeper-3.5.7/bin/zkServer.sh start"
	done
}
;;
"stop"){
	for i in 192.168.3.19 192.168.3.33 192.168.3.34
	do
		echo ----------- zookeeper $i 停止 -------------
		ssh $i "/opt/module/zookeeper-3.5.7/bin/zkServer.sh stop"
	done
}
;;
"status"){
	for i in 192.168.3.19 192.168.3.33 192.168.3.34
	do
		echo ----------- zookeeper $i 狀態 -------------
		ssh $i "/opt/module/zookeeper-3.5.7/bin/zkServer.sh status"
	done
}
;;
esac

啟動指令碼是建立在機器之前的無密遠端登入設定好的前提下,如果沒有設定好的話,在執行的過程中需要輸入對應的密碼。

[root@localhost ~]# sh zk.sh start
----------- zookeeper 192.168.3.19 啟動 -------------
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
----------- zookeeper 192.168.3.33 啟動 -------------
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
----------- zookeeper 192.168.3.34 啟動 -------------
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED

[root@localhost ~]# sh zk.sh status
----------- zookeeper 192.168.3.19 狀態 -------------
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: follower
----------- zookeeper 192.168.3.33 狀態 -------------
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: leader
----------- zookeeper 192.168.3.34 狀態 -------------
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: follower

[root@localhost ~]# sh zk.sh stop
----------- zookeeper 192.168.3.19 停止 -------------
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Stopping zookeeper ... STOPPED
----------- zookeeper 192.168.3.33 停止 -------------
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Stopping zookeeper ... STOPPED
----------- zookeeper 192.168.3.34 停止 -------------
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Stopping zookeeper ... STOPPED

客戶端

基本語法

命令基本語法 功能描述
help 顯示所有指令
is path 使用 ls 命令來檢視當前 znode 的子節點【可監聽】
-w 監聽子節點變化
-s 附加次級資訊
create 普通建立
-s 含有序列
-e 臨時(重啟或者超時消失)
get path 獲得節點的值 [可監聽]
-w 監聽節點內容變化
-s 附加次級資訊
set 設定節點的具體值
stat 檢視節點的具體值
delete 刪除節點
deleteall 遞迴刪除節點

啟動客戶端

先進入 Zookeeper 的安裝目錄:

bin/zkCli.sh -server 192.168.3.34

znode 節點資料資訊

檢視當前 znode 中所有包含的內容

[zk: 192.168.3.34(CONNECTED) 2] ls /
[zookeeper]

檢視當前 znode 中所有包含的詳細內容

[zk: 192.168.3.34(CONNECTED) 3] ls -s /
[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
引數詳解
  1. czxid:建立節點的事務 zxid

每次修改 ZooKeeper 狀態都會產生一個 ZooKeeper 事務 ID。事務 ID 是 ZooKeeper 中所 有修改總的次序。每次修改都有唯一的 zxid,如果 zxid1 小於 zxid2,那麼 zxid1 在 zxid2 之 前發生。

  1. ctime:znode 被建立的毫秒數(從 1970 年開始)
  2. mzxid:znode 最後更新的事務 zxid
  3. mtime:znode 最後修改的毫秒數(從 1970 年開始)
  4. pZxid:znode 最後更新的子節點 zxid
  5. cversion:znode 子節點變化號,znode 子節點修改次數
  6. dataversion:znode 資料變化號
  7. aclVersion:znode 訪問控制列表的變化號
  8. ephemeralOwner:如果是臨時節點,這個是 znode 擁有者的 session id。如果不是 臨時節點則是 0。
  9. dataLength:znode 的資料長度
  10. numChildren:znode 子節點數量

節點型別(持久/短暫/有序號/無序號)

簡介

持久(Persistent):客戶端和伺服器端斷開連線後,建立的節點不刪除

短暫(Ephemeral):客戶端和伺服器端斷開連線後,建立的節點自己刪除

(1)持久化目錄節點:客戶端與Zookeeper斷開連線後,該節點依舊存在

(2)持久化順序編號目錄節點:客戶端與Zookeeper斷開連線後,該節點依舊存 在,只是Zookeeper給該節點名稱進行順序編號

(3)臨時目錄節點:客戶端與Zookeeper斷開連線後,該節點被刪除

(4)臨時順序編號目錄節點:客戶端與 Zookeeper 斷開連線後 , 該 節 點 被 刪 除 , 只 是 Zookeeper給該節點名稱進行順序編號。

說明:建立znode時設定順序標識,znode名稱 後會附加一個值,順序號是一個單調遞增的計數 器,由父節點維護;

注意:在分散式系統中,順序號可以被用於 為所有的事件進行全域性排序,這樣客戶端可以通 過順序號推斷事件的順序;

實操

持久節點無序號
建立節點
[zk: 192.168.3.34(CONNECTED) 4] create /lol "luoshou"
Created /lol
[zk: 192.168.3.34(CONNECTED) 5] ls /
[lol, zookeeper]
[zk: 192.168.3.34(CONNECTED) 7] create /lol/noxus "delaiwen"
Created /lol/noxus
[zk: 192.168.3.34(CONNECTED) 8] ls /
[lol, zookeeper]
[zk: 192.168.3.34(CONNECTED) 9] ls /lol
[noxus]
獲取節點的值
[zk: 192.168.3.34(CONNECTED) 11] get -s /lol
luoshou
cZxid = 0x500000002
ctime = Thu Mar 10 23:58:31 CST 2022
mZxid = 0x500000002
mtime = Thu Mar 10 23:58:31 CST 2022
pZxid = 0x500000003
cversion = 1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 7
numChildren = 1
持久節點有序號
建立節點
[zk: 192.168.3.34(CONNECTED) 1] create -s /lol/demacia "dema"
Created /lol/demacia0000000001
[zk: 192.168.3.34(CONNECTED) 5] create -s /lol/demacia "dema"
Created /lol/demacia0000000002
獲取節點的值
[zk: 192.168.3.34(CONNECTED) 4] ls /lol
[demacia0000000001, noxus]
[zk: 192.168.3.34(CONNECTED) 6] ls /lol
[demacia0000000001, demacia0000000002, noxus]
臨時節點無序號
建立節點
[zk: 192.168.3.34(CONNECTED) 1] create -e /lol/zaun "mengduo"
Created /lol/zaun
獲取節點的值
[zk: 192.168.3.34(CONNECTED) 4] ls /lol
[demacia0000000001, demacia0000000002, noxus, zaun]
臨時節點有序號
建立節點
[zk: 192.168.3.34(CONNECTED) 8] create -e -s /lol/zaun "mengduo"
Created /lol/zaun0000000004
獲取節點的值
[zk: 192.168.3.34(CONNECTED) 11] ls /lol
[demacia0000000001, demacia0000000002, noxus, zaun, zaun0000000004]
退出客戶端後再啟動檢視

重啟後臨時節點已經無了:

[zk: 192.168.3.34(CONNECTED) 0] ls /lol
[demacia0000000001, demacia0000000002, noxus]
修改節點中的值
[zk: 192.168.3.34(CONNECTED) 1] get -s /lol/noxus
delaiwen
cZxid = 0x500000003
ctime = Fri Mar 11 00:00:07 CST 2022
mZxid = 0x500000003
mtime = Fri Mar 11 00:00:07 CST 2022
pZxid = 0x500000003
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 8
numChildren = 0

[zk: 192.168.3.34(CONNECTED) 2] set -s /lol/noxus "luoshou"
cZxid = 0x500000003
ctime = Fri Mar 11 00:00:07 CST 2022
mZxid = 0x50000000f
mtime = Fri Mar 11 00:22:40 CST 2022
pZxid = 0x500000003
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 7
numChildren = 0

[zk: 192.168.3.34(CONNECTED) 3] get -s /lol/noxus
luoshou
cZxid = 0x500000003
ctime = Fri Mar 11 00:00:07 CST 2022
mZxid = 0x50000000f
mtime = Fri Mar 11 00:22:40 CST 2022
pZxid = 0x500000003
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 7
numChildren = 0

監聽器

簡介

客戶端註冊監聽它關心的目錄節點,當目錄節點發生變化(資料改變、節點刪除、子目 錄節點增加刪除)時,ZooKeeper 會通知客戶端。監聽機制保證 ZooKeeper 儲存的任何的數 據的任何改變都能快速的響應到監聽了該節點的應用程式。

原理

  1. 首先要有一個 main() 執行緒
  2. 在 main 執行緒中建立 Zookeeper 客戶端,這時就會建立兩個執行緒,一個負責網路連線通訊(connect),一個負責監聽(listener)
  3. 通過 connect 執行緒將註冊的監聽事件傳送給 Zookeeper。
  4. 在 Zookeeper 的註冊監聽器列表中將註冊的監聽事件新增到列表中
  5. Zookeeper 監聽到有資料或路徑變化,就會將這個訊息傳送給 listener 執行緒
  6. listener 執行緒內部呼叫了 process() 方法

bIasne.md.png

常見的監聽

  1. 監聽節點資料的變化

    get path [watch]

  2. 監聽子節點增減的變化

    ls path [watch]

實操

節點值變化的監聽

四號機器註冊監聽

[zk: localhost:2181(CONNECTED) 4] get -w /lol
luoshou

三號機器修改對應節點的數值

[zk: 192.168.3.34(CONNECTED) 4] set /lol "delaiwen"

四號機器觸發監聽

[zk: localhost:2181(CONNECTED) 5]
WATCHER::

WatchedEvent state:SyncConnected type:NodeDataChanged path:/lol
節點的子節點變化的監聽(路徑變化)

四號機器註冊監聽

[zk: localhost:2181(CONNECTED) 5] ls -w /lol
[demacia0000000001, demacia0000000002, noxus]

三號機器修改對應節點,建立新的子節點

[zk: 192.168.3.34(CONNECTED) 5] create /lol/yordles "timo"
Created /lol/yordles

四號機器觸發監聽

[zk: localhost:2181(CONNECTED) 6]
WATCHER::

WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/lol

注意:註冊一次,只能監聽一次。想再次監聽,需要再次註冊。

節點刪除

# 刪除單節點
[zk: localhost:2181(CONNECTED) 7] delete /lol/yordles
# 刪除有子節點的節點
[zk: localhost:2181(CONNECTED) 9] deleteall /lol

相關文章