ZooKeeper原理詳解及常用操作


ZooKeeper是什么?

ZooKeeper是一個開源的分布式應用程序協調系統。簡稱ZK,ZK是一個典型的分布式數據一致性解決方案,分布式應用程序可以基於它實現數據的發布/訂閱、負載均衡、名稱服務、分布式協調/通知、集群管理、Master選舉、分布式鎖盒分布式隊列等等功能。它運行在JAVA環境之中,並具有JAVA和C的綁定。

ZooKeeper的設計目標

ZooKeeper允許分布式進程通過共享的分層命名空間相互協調,該命名空間的組織方式與標准文件系統類似。名稱空間由數據寄存器(在ZooKeeper中,被稱為Znodes)組成,這些寄存器類似於文件和目錄,與設計用於存儲的典型文件系統不同,ZooKeeper數據保存在內存中,這意味着ZooKeeper可以實現高吞吐量和低延遲數。ZooKeeper實現非常重視高性能、高可用性、嚴格有序的訪問,ZooKeeper的性能方面意味着它可以在大型分布式系統中使用,可靠性方面使其不會稱為單點故障,嚴格的排序意味着可以在客戶端實現復雜的同步原語。

ZooKeeper集群概念

集群角色

Leader:領導者,通過集群選舉產生的主節點,負責集群的讀與寫工作•Follower:追隨者,有資格參與集群選舉,但未能被成功選舉為Leader的備用選舉節點,負責集群的讀服務•Observer:觀察者,沒有資格參與集群選舉,負責集群的讀服務,同步Leader狀態

注意:當Leader故障之后ZooKeeper集群會通過Follower選舉新的Leader,如果老的Leader故障修復之后,會再次接管集群中的Leader腳本,新的Leader則退回Follower角色。一般集群當中無需設置Observer節點,Follower節點即可。

圖解集群

集群角色工作原理介紹:

上圖中有5個ZooKeeper節點,其中一個節點為Leader,除leader節點外,其它都是追隨者Follower,Client與ZK集群建立TCP長連接,只有追隨者Follower節點來與Client建立連接(我們的Client與Follower建立的連接會始終存在,只有Client不再參與集群或者客戶端出現故障之后才會斷開連接,是一個持久會話,通過此會話,Client會不短向自己所連接的Follower更新自己的狀態信息),並處理Client的請求,如果Client為讀請求,則會轉發到Follower或者本機進行處理,如果為寫請求則轉發給Leader處理。如果Client與連接的一台ZK集群中的服務器發生數據變更,則ZK集群中的這台服務器會把變更內容同步到ZK集群中的所有ZK服務器。

假如上圖中的Client為Kafka,一共有8台Kafka,Kafka的集群配置信息全部是由ZooKeeper來維護,如果沒有ZooKeeper,Kafka的單節點就不知道它們是個集群或者集群中共有那些節點,有了ZooKeeper之后,Kakfa節點會向ZK集群發出請求來詢問他們的Kafka一共有幾個集群節點,哪個節點還在工作,哪個節點為故障節點等等的集群信息全部都是由ZooKeeper來維護,如果想知道這些信息,Kafka就會去ZK集群節點中去請求一個數據分支,所有有了前面我們介紹ZooKeeper是的一個開源的分布式應用程序協調系統。通過ZooKeeper提供的服務來與Kafka集群的其它節點互知。

數據模型

上面講到Kafka會去ZK集群中請求一個數據分支,ZooKeeper的數據分支一個倒置樹狀的分支結構,可以說這個數據是放在ZooKeeper內存中的一個樹狀的文件系統來保存Kafka集群的數據,ZooKeeper提供的這個存儲系統非常類似於標准的文件目錄,名稱是有斜杠"/"來分割的。Kafka集群的每個節點信息都是存放在內存中的該存儲系統中,各節點信息由路徑標示,例如下圖中的/app1,就是我們的Kafka中的一個節點(此節點在ZooKeeper中被官方稱為ZNode,即ZooKeeper數據模型中的數據單元,數據模型因為為樹狀所以被稱為Znode Tree,),/app1下的/p_1-3就是存儲的這個Kafka節點的狀態信息,例如該節點變更了哪些操作,存活狀態等等。

ZNode維護一個stat結構,就是節點下面的/app1/p_1-3,維護該內容的數據數據更改,ACL更改盒時間戳的版本號,以允許緩存驗證和協調更新。每次znode的數據更改時,版本號都會增加。例如,每當客戶端檢索數據時,它也接收數據的版本。

存儲在每個ZNode的數據都是以原子方式讀取和寫入,讀取獲取與ZNode關聯的所有數據字節,寫入替換所有數據。每個節點都有一個訪問控制列表(ACL),限制誰可以做什么。ZooKeeper也有短暫節點的概念。只要創建znode的會話處於活動狀態,就會存在這些znode。會話結束時,znode將被刪除。當您想要實現[tbd]時,短暫節點很有用。ZNode的數據節點分為兩類

持久節點:一直存在,如果想要消失,僅顯示刪除才消失臨時節點:會話終止即自動消失

上面我們講到ZNode維護一個stat結構,維護該內容的數據數據更改,ACL更改盒時間戳的版本號,下面我們就講下ACL和版本號 版本(version):ZK會為每個ZNode維護一個稱之為stat的數據結構,記錄當前數據結構的三個數據版本

version:當前版本cversion:當前的znode子節點版本aversion:當前的znode的ACL版本

ACL:因為可能會有多個分布式系統使用一個ZooKeeper集群來維護集群的協調服務,那么不同分布式集群信息不能被其它機器所訪問,就出現了ZooKeeper使用ACL機制進行權限控制。

CREATE:創建READ:讀WRITE:寫DELETE:刪ADMIN:管理

ZAB協議

ZooKeeper(ZooKeeper Atomic Broadcast,ZooKeeper原子廣播協議)是通過ZAB協議來完成了Client各個節點選舉的信息,ZAB協議是整個ZooKeeper的核心,支持崩潰保護機制,用於在Leader崩潰時重新選舉出新的Leader,而且還要確保數據的完整性和一至性,此協議不僅能夠保證ZooKeeper集群本身的選舉,還能管理使用ZooKeeper協調服務的分布式程序的選舉工作。

ZAB協議中存在的三種狀態:

(1)Looking:集群剛啟動,開始選舉Leader,或者Leader崩潰之后再次選舉新的Leader時,正在選舉,被稱為Looking狀態。

(2)Following:Following就是Follower狀態,這個時候集群中已經存在Leader,這些機器屬於Follover節點稱之為Following狀態。

(3)Leading:Leader就被稱為Leading狀態。

ZAB協議中的存在的四個階段:

•選舉:election•發現:discovery•同步:sync•廣播:Broadcast

部署ZooKeeper

ZooKeeper下載:

wget https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/zookeeper-3.4.14/zookeeper-3.4.14.tar.gz

解壓並安裝

tar xf zookeeper-3.4.14.tar.gz -C /application/
cp /application/zookeeper-3.4.14/conf/zoo_sample.cfg /application/zookeeper-3.4.14/conf/zoo.cfg

添加環境變量

cat << EOF >> /etc/profile
export ZOOKEEPER_HOME=/application/zookeeper-3.4.14
export PATH=\$PATH:\$ZOOKEEPER_HOME/binEOF
source /etc/profile

修改ZooKeeper配置

cat /application/zookeeper-3.4.14/conf/zoo.cfg

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/application/zookeeper-3.4.14/data
dataLogDir=/application/zookeeper-3.4.14/logs
clientPort=2181
maxClientCnxns=60
autopurge.snapRetainCount=3
autopurge.purgeInterval=1
server.1=localhost:2888:3888

創建數據存儲目錄及日志目錄

mkdir /application/zookeeper-3.4.14/{data,logs}

ZooKeeper配置詳解

tickTime=2000
#ZooKeeper服務器之間或客戶單與服務器之間維持心跳的時間間隔,單位是毫秒,默認為2000。
initLimit=10
#zookeeper接受客戶端(這里所說的客戶端不是用戶連接zookeeper服務器的客戶端,而是zookeeper服務器集群中連接到leader的follower 服務器)初始化連接時最長能忍受多少個心跳時間間隔數。
#當已經超過10個心跳的時間(也就是tickTime)長度后 zookeeper 服務器還沒有收到客戶端的返回信息,那么表明這個客戶端連接失敗。總的時間長度就是 10*2000=20秒。
syncLimit=5
#標識ZooKeeper的leader和follower之間同步消息,請求和應答時間長度,最長不超過多少個tickTime的時間長度,總的時間長度就是5*2000=10秒。
dataDir=/application/zookeeper-3.4.14/data
#存儲內存數據庫快照的位置;ZooKeeper保存Client的數據都是在內存中的,如果ZooKeeper節點故障或者服務停止,那么ZooKeeper就會將數據快照到該目錄當中。
clientPort=2181
#ZooKeeper客戶端連接ZooKeeper服務器的端口,監聽端口
maxClientCnxns=60
#ZooKeeper可接受客戶端連接的最大數量,默認為60
dataLogDir=/application/zookeeper-3.4.14/logs
#如果沒提供的話使用的則是dataDir。zookeeper的持久化都存儲在這兩個目錄里。dataLogDir里是放到的順序日志(WAL)。而dataDir里放的是內存數據結構的snapshot,便於快速恢復。
為了達到性能最大化,一般建議把dataDir和dataLogDir分到不同的磁盤上,這樣就可以充分利用磁盤順序寫的特性

autopurge.snapRetainCount=3
#ZooKeeper要保留dataDir中快照的數量
autopurge.purgeInterval=1
#ZooKeeper清楚任務間隔(以小時為單位),設置為0表示禁用自動清除功能
server.1=localhost:2888:3888
#指定ZooKeeper集群主機地址及通信端口#1 為集群主機的數字標識,一般從1開始,三台ZooKeeper集群一般都為123#localhost 為集群主機的IP地址或者可解析主機名
#2888 端口用來集群成員的信息交換端口,用於ZooKeeper集群節點與leader進行信息同步#3888 端口是在leader掛掉時或者剛啟動ZK集群時專門用來進行選舉leader所用的端口

啟動ZooKeeper

/application/zookeeper-3.4.14/bin/zkServer.sh start
ZooKeeper JMX enabled by default
Using
config: /application/zookeeper-3.4.14/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
查看ZK狀態
/application/zookeeper-3.4.14/bin/zkServer.sh status
ZooKeeper JMX enabled by defaultUsing
config: /application/zookeeper-3.4.14/bin/../conf/zoo.cfg
Mode: standalone
ss -anplt | grep 2181LISTEN 0 50 :::2181 :::* users:(("java",pid=17168,fd=27))

ZooKeeper執行程序簡介

ls /application/zookeeper-3.4.14/bin/ -l
total 44
-rwxr-xr-x 1 2002 2002 232 Mar 7 00:50 README.txt
-rwxr-xr-x 1 2002 2002 1937 Mar 7 00:50 zkCleanup.sh
-rwxr-xr-x 1 2002 2002 1056 Mar 7 00:50 zkCli.cmd
-rwxr-xr-x 1 2002 2002 1534 Mar 7 00:50 zkCli.sh #ZK客戶端連接ZK的腳本程序
-rwxr-xr-x 1 2002 2002 1759 Mar 7 00:50 zkEnv.cmd
-rwxr-xr-x 1 2002 2002 2919 Mar 7 00:50 zkEnv.sh #ZK變量腳本程序
-rwxr-xr-x 1 2002 2002 1089 Mar 7 00:50 zkServer.cmd
-rwxr-xr-x 1 2002 2002 6773 Mar 7 00:50 zkServer.sh #ZK啟動腳本程序
-rwxr-xr-x 1 2002 2002 996 Mar 7 00:50 zkTxnLogToolkit.cmd
-rwxr-xr-x 1 2002 2002 1385 Mar 7 00:50 zkTxnLogToolkit.sh

zkServer.sh啟動文件

zkServer.sh通常用來啟動、終止、重啟ZK服務器,用法如下:

/application/zookeeper-3.4.14/bin/zkServer.sh 
ZooKeeper JMX enabled by default
Using config: /application/zookeeper-3.4.14/bin/../conf/zoo.cfg
Usage: /application/zookeeper-3.4.14/bin/zkServer.sh {start|start-foreground|stop|restart|status|upgrade|print-cmd}
#關閉ZK服務/application/zookeeper-3.4.14/bin/zkServer.sh stop
#啟動ZK服務/application/zookeeper-3.4.14/bin/zkServer.sh start
#啟動ZK服務並打印啟動信息到標准輸出,方便於排錯/application/zookeeper-3.4.14/bin/zkServer.sh start-foreground
#重啟ZK服務/application/zookeeper-3.4.14/bin/zkServer.sh restart
#查看ZK服務狀態/application/zookeeper-3.4.14/bin/zkServer.sh status

zkCli.sh客戶端連接

zkCli.sh是用來連接zk服務的腳本程序文件,使用該腳本程序連接到ZK后,可管理ZK服務,用法如下:

 

 

 

create [-s] [-e] path data acl 選項介紹: -s用來指定節點特性為順序節點;順序節點:是創建時唯一且被獨占的遞增性整數作為其節點號碼,此號碼會被疊加在路徑之后。 -e用來指定特性節點為臨時節點,臨時節點不允許有子目錄;關於持久節點和臨時節點請看上篇文章 若不指定,則表示持久節點 acl用來做權限控制

創建ZooKeeper持久節點

#創建持久節點permanent,關聯字符串permanent[zk: localhost:2181(CONNECTED) 0] 
create /permanent "permanent"
Created /permanent
#在持久節點permanent下創建子目錄zk-node1和zk-nod2
[zk: localhost:2181(CONNECTED) 1]create /permanent/zk_node1
"zk_node1"
Created /permanent/zk_node1
[zk: localhost:2181(CONNECTED) 2]create /permanent/zk_node2
"zk_node2"
Created /permanent/zk_node2
#查看創建的zk數據文件
[zk: localhost:2181(CONNECTED) 3] ls /[zookeeper, permanent]
[zk: localhost:2181(CONNECTED) 4] ls /permanent[zk_node1, zk_node2]

創建ZooKeeper順序節點

#創建順序節點order,關聯字符串order,創建好之后並不會以我們創建的order命名,zk會自動在后面加上一排遞增數字來顯示此文件夾,遞增數據不會從重復
[zk: localhost:2181(CONNECTED) 5] create -s /order "order"Created /order0000000004
[zk: localhost:2181(CONNECTED) 6] ls /[zookeeper, permanent, order0000000004]
#我們再次創建一個順序節點,會發現后面的增至數字默認加1,並沒有重復
[zk: localhost:2181(CONNECTED) 8] create -s /tow_order "two_order"Created /tow_order0000000005
[zk: localhost:2181(CONNECTED) 9] ls /[tow_order0000000005, zookeeper, permanent, order0000000004]
#創建順序節點order的子節點
[zk: localhost:2181(CONNECTED) 10] create -s /order0000000004/order_node1
"order_node1"
Created /order0000000004/order_node10000000000

創建ZooKeeper臨時節點

#創建臨時節點temp
[zk: localhost:2181(CONNECTED) 15] create -e /temp
"temp"
Created /temp
[zk: localhost:2181(CONNECTED) 16] ls /
#查看已經創建完成的臨時節點
temp
[tow_order0000000005, temp, zookeeper, permanent, order0000000004]
#在臨時節點temp中創建子目錄,
[zk: localhost:2181(CONNECTED) 17] create -e /temp/two_temp
"tow_temp"
Ephemerals cannot have children: /temp/two_temp
#你會發現創建子目錄,ZK給你報錯誤說”臨時節點不允許子目錄存在。我們上面也說過了,臨時節點不允許存在子目錄
[zk: localhost:2181(CONNECTED) 18] ls /temp
#查看臨時節點/temp下,並沒有我們所創建的two_temp子目錄
[]
#測試臨時節點#創建的臨時節點如果當前客戶端斷開了連接后臨時節點會自動消失,而持久節點和順序節點則需要使用刪除命令來消失
#退出當前ZK連接,再次連接到ZK
[zk: localhost:2181(CONNECTED) 19] quit
#退出當前ZK連接
/application/zookeeper-3.4.14/bin/zkCli.sh -server localhost:2181
#再次連接到ZK

#查看臨時目錄是否存在
[zk: localhost:2181(CONNECTED) 0] ls /
[tow_order0000000005, zookeeper, permanent, order0000000004]
#當我們結束當前客戶端連接后,ZK的臨時節點temp也會隨之消失

 

 

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM