zookeeper萬(wàn)字雄文總結(jié)(深度)

一、Zookeeper介紹
1.1 什么是zookeeper
Zookeeper是一個(gè)分布式的、高性能的、開源的分布式系統(tǒng)的協(xié)調(diào)(Coordination)服務(wù),是Google的Chubby一個(gè)開源的實(shí)現(xiàn),是Hadoop和Hbase的一個(gè)重要的組件。它是一個(gè)為分布式應(yīng)用提供一致性服務(wù)的軟件。

1.2 zookeeper應(yīng)用場(chǎng)景
zookeeper是一個(gè)經(jīng)典的分布式數(shù)據(jù)一致性解決方案,致力于為分布式應(yīng)用提供一個(gè)高性能,高可用,且具有嚴(yán)格屬性訪問(wèn)控制能力的分布式協(xié)調(diào)存儲(chǔ)服務(wù)。

維護(hù)配置信息
分布式鎖服務(wù)
集群管理
生成分布式唯一ID
維護(hù)配置信息
java編程經(jīng)常會(huì)遇到配置項(xiàng),比如數(shù)據(jù)庫(kù)的url,schema,user和password等。通常這些配置項(xiàng)我們會(huì)放置在配置文件中,在將配置文件放置在服務(wù)器上當(dāng)需要更改配置的時(shí),需要去服務(wù)器上修改對(duì)應(yīng)的配置信息文件。但是隨著分布式系統(tǒng)的興起,由于許多服務(wù)都需要使用到該配置文件,因此有必須保證該配置服務(wù)的高可用性和各臺(tái)服務(wù)器上配置數(shù)據(jù)的一致性。通常會(huì)將配置文件部署在一個(gè)集群上,然而一個(gè)集群動(dòng)輒上千臺(tái)服務(wù)器,此時(shí)如果在一臺(tái)一臺(tái)服務(wù)器逐個(gè)的修改配置文件將是非常繁瑣的一個(gè)操作。因此就需要一種服務(wù),能夠高效快速且可靠的完成配置項(xiàng)的等待操作,并能夠保證各個(gè)配置項(xiàng)在每一臺(tái)服務(wù)器上的數(shù)據(jù)一致性。

zookeeper就可以提供這樣一種服務(wù),其使用Zab這種一致性協(xié)議來(lái)保證一致性。現(xiàn)在有很多開源項(xiàng)目使用zookeeper來(lái)維護(hù)配置,比如hhase中,客戶端就是連接一個(gè)zookeeper,獲得必要hbase集群的配置信息然后才可以進(jìn)一步操作。還有開源的消息隊(duì)列kafka中,也是用zookeeper來(lái)維護(hù)broker的信息。

分布式鎖服務(wù)
一個(gè)集群是一個(gè)分布式系統(tǒng),由多臺(tái)服務(wù)器組成。為了提高并發(fā)度和可靠性,多臺(tái)服務(wù)器運(yùn)行著同一種服務(wù)。當(dāng)多個(gè)服務(wù)在運(yùn)行時(shí)就需要協(xié)調(diào)各服務(wù)的進(jìn)度,有時(shí)候需要保證當(dāng)某個(gè)服務(wù)在進(jìn)行某個(gè)操作時(shí),其他的服務(wù)都不能進(jìn)行該操作,即對(duì)該操作進(jìn)行加鎖,如果當(dāng)前機(jī)器掛掉后,并釋放fail over到其他的機(jī)器繼續(xù)執(zhí)行該服務(wù)。



集群管理
一個(gè)集群優(yōu)勢(shì)會(huì)因?yàn)楦鞣N軟硬件故障或者網(wǎng)絡(luò)故障,出現(xiàn)某種服務(wù)器掛掉而被移除集群,而某些服務(wù)器加入到集群中的情況,zookeeper會(huì)將這些服務(wù)器加入/移出的情況下通知給集群匯總的其他正常工作的服務(wù)器,以及時(shí)調(diào)用存儲(chǔ)和計(jì)算等任務(wù)的分配和執(zhí)行等。此外zookeeper還會(huì)對(duì)故障的服務(wù)器做出診斷并嘗試修復(fù)。



  4.  生成分布式唯一ID

在過(guò)去的單庫(kù)單表型系統(tǒng)中,通??梢允褂脭?shù)據(jù)庫(kù)字段自帶的auto_increment屬性來(lái)自動(dòng)為每條記錄生成一個(gè)唯一的ID。但是分庫(kù)分表后,就無(wú)法再依靠數(shù)據(jù)庫(kù)的auto_increatment屬性來(lái)唯一標(biāo)識(shí)一條記錄了,此時(shí)我們就可以用zookeeper在分布式環(huán)境下生成全局唯一ID。做法如下:每一個(gè)生成一個(gè)新ID時(shí),創(chuàng)建一個(gè)持久順序節(jié)點(diǎn),創(chuàng)建操作返回的節(jié)點(diǎn)序號(hào),及微信ID,然后把比自己節(jié)點(diǎn)小的刪除即可。

1.3 zookeeper的設(shè)計(jì)目標(biāo)
zookeeper致力于為分布式應(yīng)用提供一個(gè)高性能,高可用,具有嚴(yán)格順序訪問(wèn)控制能力的分布式協(xié)調(diào)服務(wù)。

高性能
zookeeper將全量數(shù)據(jù)存儲(chǔ)在內(nèi)存中,并直接發(fā)起與客戶端的所有非事務(wù)請(qǐng)求,尤其適合用于以讀為主的應(yīng)用場(chǎng)景。

高可用
zookeeper一般以集群的方式對(duì)外提供服務(wù),一般3-5臺(tái)機(jī)器就可以組成一個(gè)可用的zookeeper集群,每一臺(tái)機(jī)器都會(huì)在內(nèi)存中維護(hù)當(dāng)前的服務(wù)器狀態(tài),并且每臺(tái)機(jī)器之間都相互保持著通信。只要集群中超過(guò)一旦的機(jī)器都在工作,那么這個(gè)集群就能夠正常對(duì)外服務(wù);

嚴(yán)格訪問(wèn)數(shù)據(jù)
對(duì)于客戶端的每一個(gè)更新請(qǐng)求,Zookeeper都會(huì)分配一個(gè)全局唯一的遞增編號(hào),這個(gè)編號(hào)反映了所有事物操作的先后順序。

二、Zookeeper的數(shù)據(jù)模型
2.1. zookeeper數(shù)據(jù)結(jié)構(gòu)
Zookeeper數(shù)據(jù)模型的結(jié)構(gòu)與Unix文件系統(tǒng)很類似,整體上可以看作是一顆樹,每一個(gè)節(jié)點(diǎn)稱做一個(gè)ZNode。每一個(gè)Znode默認(rèn)能夠存儲(chǔ)1MB的數(shù)據(jù),每個(gè)ZNode都可以通過(guò)其路徑唯一標(biāo)識(shí)。



 如何來(lái)描述一個(gè)ZNode呢?一個(gè)znode大體上分為3部分:

節(jié)點(diǎn)的數(shù)據(jù):即znode data(節(jié)點(diǎn)path,節(jié)點(diǎn)data的關(guān)系)就像是java map中(key,value)的關(guān)系
節(jié)點(diǎn)的子節(jié)點(diǎn)children
節(jié)點(diǎn)的狀態(tài)stat:用來(lái)描述當(dāng)前節(jié)點(diǎn)的創(chuàng)建,修改記錄,包括cZxid、ctime等。
2.2 zookeeper節(jié)點(diǎn)類型
zookeeper中的節(jié)點(diǎn)有兩種類型,一種是臨時(shí)節(jié)點(diǎn)和永久節(jié)點(diǎn)。節(jié)點(diǎn)類型在創(chuàng)建時(shí)即被確定,并且不能改變。

臨時(shí)節(jié)點(diǎn) :該節(jié)點(diǎn)的生命周期依賴于創(chuàng)建他們的會(huì)話。一旦會(huì)話(Session)結(jié)束,臨時(shí)節(jié)點(diǎn)將會(huì)被自動(dòng)刪除,當(dāng)然可以手動(dòng)的進(jìn)行刪除。雖然每個(gè)臨時(shí)的ZNode都會(huì)綁定到一個(gè)客戶端回話,但他們對(duì)所有的客戶端還是可見(jiàn)的。另外,Zookeeper的臨時(shí)節(jié)點(diǎn)不允許擁有子節(jié)點(diǎn)。
持久化節(jié)點(diǎn):該節(jié)點(diǎn)的生命周期不依賴于花花,并且只有在客戶點(diǎn)顯示執(zhí)行刪除操作的時(shí)候,他們才能被刪除。
2.3 zookeeper 單機(jī)安裝
當(dāng)前測(cè)試系統(tǒng)環(huán)境centos7.3

在centos中使用root用戶創(chuàng)建zookeeper用戶,用戶名:zookeeper  密碼:zookeeper
useradd zookeeper
passwd zookeeper
zookeeper 底層依賴jdk,zookeeper用戶登錄后,根目錄下先進(jìn)行jdk的安裝,jdk使用jdk-11.0.5
//解壓jdk
tar -xzvf jdk-11.0.5.tar.gz
配置jdk環(huán)境量
//打開/etc/profile文件
# vim /etc/profile
export JAVA_HOME=/root/apps/jdk-11.0.5
export PATH=$PATH:$JAVA_HOME/bin
//執(zhí)行profile
#source /etc/profile
zookeeper使用zookeeper-3.4.10.tar.gz,上傳并解壓
//解壓zookeeper
tar -xzvf zookeeper-3.4.10.tar.gz
為zookeeper準(zhǔn)備配置文件
//進(jìn)入conf目錄
cd /root/apps/zookeeper/zookeeper-3.4.14/conf
//復(fù)制配置文件
cp zoo_sample.cfg zoo.cfg
//zookeeper根目錄下新建data目錄
mkdir data
// vi 修改配置文件中的dataDir
// 此路徑用于存儲(chǔ)zookeeper中數(shù)據(jù)的內(nèi)存快照,及事務(wù)日志文件
dataDir=/root/apps/zookeeper/zookeeper-3.4.14/data








 6. zookeeper啟動(dòng)命令

[root@centos ~]# systemctl stop firewalld #關(guān)閉防火墻的命令
[root@centos ~]# zkServer.sh start  #啟動(dòng)
[root@centos ~]# zkServer.sh stop   #關(guān)閉
[root@centos ~]# zkServer.sh status #查看運(yùn)行狀態(tài)

啟動(dòng)客戶端:
[root@localhost ~]# zkCli.sh   //啟動(dòng)客戶端
[zk: localhost:2181(CONNECTED) 0] ls /  #查看根節(jié)點(diǎn)命令
//查看zookeeper進(jìn)程是否存在
[root@centos zookeeper-3.4.14]# ps -ef | grep zookeeper
三、zookeeper常用的Shell命令
3.1 新增節(jié)點(diǎn)
create [-s] [-e] path data   # 其中 -s 為有序節(jié)點(diǎn), -e 臨時(shí)節(jié)點(diǎn)
創(chuàng)建持久化節(jié)點(diǎn)并寫入數(shù)據(jù):
create /hadoop  "123456"
創(chuàng)建持久化有序節(jié),此時(shí)創(chuàng)建的節(jié)點(diǎn)名為指定節(jié)點(diǎn)名+自增序號(hào)
//創(chuàng)建一個(gè)持久化節(jié)點(diǎn)
[zk: localhost:2181(CONNECTED) 1] create /hadoop "123456"
//通過(guò)get命令獲取該節(jié)點(diǎn)的值
[zk: localhost:2181(CONNECTED) 2] get /hadoop
//創(chuàng)建一個(gè)有序的節(jié)點(diǎn)
[zk: localhost:2181(CONNECTED) 4] create -s /a "aa"
Created /a0000000001
//獲取路徑的值
[zk: localhost:2181(CONNECTED) 5] get /a0000000001
aa

//創(chuàng)建臨時(shí)節(jié)點(diǎn)并獲取值
[zk: localhost:2181(CONNECTED) 1] create -e /tmp "tmp"
Created /tmp
[zk: localhost:2181(CONNECTED) 2] get /tmp
tmp
創(chuàng)建臨時(shí)節(jié)點(diǎn),臨時(shí)節(jié)點(diǎn)會(huì)在回話過(guò)期后被刪除;
[zk: localhost:2181(CONNECTED) 1] create -e /tmp "tmp"
Created /tmp
創(chuàng)建臨時(shí)有序節(jié)點(diǎn),臨時(shí)節(jié)點(diǎn)會(huì)在會(huì)話過(guò)期后被刪除:
[zk: localhost:2181(CONNECTED) 1] create -s -e /tmp "tmp"
Created /tmp000000001
3.2 更新節(jié)點(diǎn)
//使用set命令來(lái)更新hadoop節(jié)點(diǎn)
[zk: localhost:2181(CONNECTED) 1] set /hadoop "345"
//根據(jù)版本號(hào)來(lái)更新節(jié)點(diǎn)
[zk: localhost:2181(CONNECTED) 1] set /hadoop "345" 2
也可以基于版本號(hào)來(lái)進(jìn)行更改,此時(shí)類似于樂(lè)觀鎖機(jī)制,當(dāng)你傳入的數(shù)據(jù)版本號(hào)(dataVersion)和當(dāng)前節(jié)點(diǎn)的數(shù)據(jù)版本號(hào)不符合時(shí),zookeeper會(huì)拒絕本次修改:

3.3 刪除節(jié)點(diǎn)
刪除節(jié)點(diǎn)的命令如下
delete path [version]
和更新節(jié)點(diǎn)數(shù)據(jù)一樣,也可以傳入版本號(hào),當(dāng)你傳入的數(shù)據(jù)版本號(hào)(dataVersion)和當(dāng)前節(jié)點(diǎn)的數(shù)據(jù)版本號(hào)不符合時(shí),zookeeper不會(huì)執(zhí)行刪除操作。

//根據(jù)版本號(hào)來(lái)刪除節(jié)點(diǎn)
[zk: localhost:2181(CONNECTED) 1] set /hadoop "345" 2
要想刪除某個(gè)節(jié)點(diǎn)及其所有后代節(jié)點(diǎn),可以使用遞歸刪除,命令為 rmr path。

3.4 查看節(jié)點(diǎn)
get path
[zk: localhost:2181(CONNECTED) 1] get /hadoop
[zk: localhost:2181(CONNECTED) 0] create /hadoop2 "hadoop"
Created /hadoop2
[zk: localhost:2181(CONNECTED) 1] get /hadoop2
hadoop
cZxid = 0xb
ctime = Thu May 14 09:06:29 CST 2020
mZxid = 0xb
mtime = Thu May 14 09:06:29 CST 2020
pZxid = 0xb
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 6
numChildren = 0
[zk: localhost:2181(CONNECTED) 2]
節(jié)點(diǎn)各個(gè)屬性如下表。其中一個(gè)重要的概念是Zxid(ZooKeeper Transaction Id),ZooKeeper節(jié)點(diǎn)的每一個(gè)更改都具唯一的Zxid,如果Zxid1小于Zxid2,則Zxid1的更改發(fā)生在Zxid2更改之前。



3.5 查看節(jié)點(diǎn)狀態(tài)
可以使用stat命令查看節(jié)點(diǎn)狀態(tài),它的返回值和get命令類似,但不會(huì)返回節(jié)點(diǎn)數(shù)據(jù)

//使用stat命令來(lái)查看節(jié)點(diǎn)狀態(tài)
[zk: localhost:2181(CONNECTED) 0] stat /hadoop
cZxid = 0x4
ctime = Thu May 14 07:56:33 CST 2020
mZxid = 0x4
mtime = Thu May 14 07:56:33 CST 2020
pZxid = 0x4
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 6
numChildren = 0
[zk: localhost:2181(CONNECTED) 1]
3.6 查看節(jié)點(diǎn)列表
查看節(jié)點(diǎn)列表有l(wèi)s path 和ls2 path 兩個(gè)命令,后者是前者的增強(qiáng)。不僅可以查看指定路徑下的所有節(jié)點(diǎn),還可以查看當(dāng)前幾點(diǎn)的信息

[zk: localhost:2181(CONNECTED) 5] ls /
[a0000000001, hadoop, zookeeper, tmp, hadoop2]
[zk: localhost:2181(CONNECTED) 6] ls2 /
[a0000000001, hadoop, zookeeper, tmp, hadoop2]
cZxid = 0x0
ctime = Thu Jan 01 08:00:00 CST 1970
mZxid = 0x0
mtime = Thu Jan 01 08:00:00 CST 1970
pZxid = 0xb
cversion = 3
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 5
[zk: localhost:2181(CONNECTED) 7]
3.7 監(jiān)聽(tīng)器get path [watch]
使用get path [watch] 注冊(cè)的監(jiān)聽(tīng)器能夠在節(jié)點(diǎn)內(nèi)容發(fā)生改變的時(shí)候,向客戶點(diǎn)發(fā)出通知。需要注意的是zookeeper的觸發(fā)器是一次性的(One-time trigger),觸發(fā)一次后就會(huì)立即失效。

[zk: localhost:2181(CONNECTED) 8] get /hadoop watch
123456
cZxid = 0x4
ctime = Thu May 14 07:56:33 CST 2020
mZxid = 0x4
mtime = Thu May 14 07:56:33 CST 2020
pZxid = 0x4
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 6
numChildren = 0
[zk: localhost:2181(CONNECTED) 9]
WATCHER::

WatchedEvent state:SyncConnected type:NodeDataChanged path:/hadoop
3.8 監(jiān)聽(tīng)器stat path [watch]
使用stat path [watch] 注冊(cè)的監(jiān)聽(tīng)器能夠在節(jié)點(diǎn)抓哪個(gè)臺(tái)發(fā)生改變的時(shí)候,向客戶點(diǎn)發(fā)出通知。

[zk: localhost:2181(CONNECTED) 1] stat /hadoop watch
cZxid = 0x4
ctime = Thu May 14 07:56:33 CST 2020
mZxid = 0xf
mtime = Thu May 14 10:01:04 CST 2020
pZxid = 0x4
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 6
numChildren = 0
[zk: localhost:2181(CONNECTED) 2]
WATCHER::

WatchedEvent state:SyncConnected type:NodeDataChanged path:/hadoop
3.9 監(jiān)聽(tīng)器ls\ls2 path [watch]
使用 ls path [watch] 或者 ls2 path [watch] 注冊(cè)的監(jiān)聽(tīng)器能夠監(jiān)聽(tīng)該節(jié)點(diǎn)下所有子節(jié)點(diǎn)的增加和刪除操作。

四、zookeeper權(quán)限控制
4.1 概述
zookeeper類似于文件系統(tǒng),client可以創(chuàng)建節(jié)點(diǎn),更新節(jié)點(diǎn),刪除節(jié)點(diǎn),那么如何做到節(jié)點(diǎn)的權(quán)限的控制呢?zookeeper的access control list 訪問(wèn)控制列表可以連接到這一點(diǎn)。acl權(quán)限控制,使用scheme:id:permission來(lái)表示,主要涵蓋3個(gè)方面:

權(quán)限模式(scheme):授權(quán)的策略

授權(quán)對(duì)象(id):授權(quán)的對(duì)象

權(quán)限(permission):授予的權(quán)限 其特性如下:

zookeeper的權(quán)限控制是基于每個(gè)znode節(jié)點(diǎn)的,需要對(duì)每個(gè)節(jié)點(diǎn)設(shè)置權(quán)限

每個(gè)znode支持設(shè)置多種權(quán)限控制方案和多個(gè)權(quán)限

子節(jié)點(diǎn)不會(huì)繼承父節(jié)點(diǎn)的權(quán)限,客戶點(diǎn)無(wú)權(quán)訪問(wèn)某個(gè)節(jié)點(diǎn),但可能可以訪問(wèn)他的子節(jié)點(diǎn)

setAcl /test2 ip:192.168.60.130:rewda //將節(jié)點(diǎn)權(quán)限設(shè)置為Ip:19
2.168.60.130的客戶端可以對(duì)節(jié)點(diǎn)進(jìn)行增、刪、改、查、權(quán)限管理
4.2 權(quán)限模式
采用何種方式授權(quán)



4.3 授權(quán)的對(duì)象
給誰(shuí)授權(quán) 授權(quán)對(duì)象ID是指,權(quán)限賦予的實(shí)體例如:ip地址或用戶。

4.4 授予的權(quán)限
授予什么權(quán)限

create、delete、read、writer、admin也就是增、刪、改、查、管理權(quán)限,這5種權(quán)限簡(jiǎn)寫為cdrwa、注意:這5種權(quán)限中,delete是指對(duì)子節(jié)點(diǎn)的刪除權(quán)限,其他4種權(quán)限只()對(duì)自身節(jié)點(diǎn)的權(quán)限操作。








4.5 授權(quán)的相關(guān)命令










4.6 案例
world授權(quán)模式:命令
setAcl <path> world:anyone:<acl>
setAcl /hadoop world:anyone:cdrwa
案例

[zk: localhost:2181(CONNECTED) 2] getAcl /hadoop
'world,'anyone   #world方式對(duì)所有用戶進(jìn)行授權(quán)
: cdrwa          #增、刪、改、查、管理
[zk: localhost:2181(CONNECTED) 3]
IP 授權(quán)模式 命令
#需要兩臺(tái)機(jī)器來(lái)進(jìn)行連接 192.168.60.129  192.168.60.130
#使用 192.168.60.129  登錄zookeeper
zkCli.sh -server 192.168.60.130
#使用本機(jī)  192.168.60.130 zookeeper
zkCli.sh -server 192.168.60.130
Auth授權(quán)模式 命令
addauth digest <user>:<password> #添加認(rèn)證用戶
setAcl <path>auth:<user>:<acl>
案例



Digest 授權(quán)模式 命令
setAcl <path> digest:<user>:<password>:<acl>
這里的密碼是經(jīng)過(guò)SHA1及BASE64處理的密文,在SHEEL中可以通過(guò)命令計(jì)算:

echo -n <user>:<password> | openssl dgst -binary -sha1 | openssl base64
先來(lái)計(jì)算一個(gè)密文

echo -n tyx:123 | openssl dgst -binary -sha1 | openssl base64
#得到的密文
[root@centos zookeeper-3.4.14]# echo -n tyx:123 | openssl dgst -binary -sha1 | openssl base64
nSk0WYb+XoISHNhIQiQ1BGsZHjE=
案例:



多種密室授權(quán):同一個(gè)節(jié)點(diǎn)可以同時(shí)使用多種模式授權(quán)
[zk: localhost:2181(CONNECTED) 8] create /hadoop4 "hadoop4"
Created /hadoop4
//添加認(rèn)證用戶
[zk: localhost:2181(CONNECTED) 8] addauth digest itcast:123456
[zk: localhost:2181(CONNECTED) 8] setAcl /hadoop4 ip:192.168.60.129:cdrwa,auth:tyx:123:cdrwa,digest:tyx:nSk0WYb+XoISHNhIQiQ1BGsZHjE=:cdrwa
4.7 acl 超級(jí)管理員
zookeeper的權(quán)限管理模式有一種叫做super,該模式提供一個(gè)超級(jí)管理員,可以訪問(wèn)任何權(quán)限的節(jié)點(diǎn)

假設(shè)這個(gè)超級(jí)管理員是:super:admin,需要先為超級(jí)管理員生成密碼的密文

echo -n super:admin | openssl dgst -binary -sha1 | openssl base64
那么打開zookeeper目錄下的/bin/zkServer.sh 服務(wù)器腳本,找到如下一行:



之后啟動(dòng)zookeeper,輸入如下的命令添加權(quán)限

addauth digest super:admin  #添加認(rèn)證用戶

作者:教你學(xué)懂大數(shù)據(jù)


歡迎關(guān)注微信公眾號(hào) :教你學(xué)懂大數(shù)據(jù)