zookeeper萬字雄文總結(jié)(深度)
一、Zookeeper介紹
1.1 什么是zookeeper
Zookeeper是一個分布式的、高性能的、開源的分布式系統(tǒng)的協(xié)調(diào)(Coordination)服務,是Google的Chubby一個開源的實現(xiàn),是Hadoop和Hbase的一個重要的組件。它是一個為分布式應用提供一致性服務的軟件。
1.2 zookeeper應用場景
zookeeper是一個經(jīng)典的分布式數(shù)據(jù)一致性解決方案,致力于為分布式應用提供一個高性能,高可用,且具有嚴格屬性訪問控制能力的分布式協(xié)調(diào)存儲服務。
維護配置信息
分布式鎖服務
集群管理
生成分布式唯一ID
維護配置信息
java編程經(jīng)常會遇到配置項,比如數(shù)據(jù)庫的url,schema,user和password等。通常這些配置項我們會放置在配置文件中,在將配置文件放置在服務器上當需要更改配置的時,需要去服務器上修改對應的配置信息文件。但是隨著分布式系統(tǒng)的興起,由于許多服務都需要使用到該配置文件,因此有必須保證該配置服務的高可用性和各臺服務器上配置數(shù)據(jù)的一致性。通常會將配置文件部署在一個集群上,然而一個集群動輒上千臺服務器,此時如果在一臺一臺服務器逐個的修改配置文件將是非常繁瑣的一個操作。因此就需要一種服務,能夠高效快速且可靠的完成配置項的等待操作,并能夠保證各個配置項在每一臺服務器上的數(shù)據(jù)一致性。
zookeeper就可以提供這樣一種服務,其使用Zab這種一致性協(xié)議來保證一致性。現(xiàn)在有很多開源項目使用zookeeper來維護配置,比如hhase中,客戶端就是連接一個zookeeper,獲得必要hbase集群的配置信息然后才可以進一步操作。還有開源的消息隊列kafka中,也是用zookeeper來維護broker的信息。
分布式鎖服務
一個集群是一個分布式系統(tǒng),由多臺服務器組成。為了提高并發(fā)度和可靠性,多臺服務器運行著同一種服務。當多個服務在運行時就需要協(xié)調(diào)各服務的進度,有時候需要保證當某個服務在進行某個操作時,其他的服務都不能進行該操作,即對該操作進行加鎖,如果當前機器掛掉后,并釋放fail over到其他的機器繼續(xù)執(zhí)行該服務。
集群管理
一個集群優(yōu)勢會因為各種軟硬件故障或者網(wǎng)絡故障,出現(xiàn)某種服務器掛掉而被移除集群,而某些服務器加入到集群中的情況,zookeeper會將這些服務器加入/移出的情況下通知給集群匯總的其他正常工作的服務器,以及時調(diào)用存儲和計算等任務的分配和執(zhí)行等。此外zookeeper還會對故障的服務器做出診斷并嘗試修復。
4. 生成分布式唯一ID
在過去的單庫單表型系統(tǒng)中,通常可以使用數(shù)據(jù)庫字段自帶的auto_increment屬性來自動為每條記錄生成一個唯一的ID。但是分庫分表后,就無法再依靠數(shù)據(jù)庫的auto_increatment屬性來唯一標識一條記錄了,此時我們就可以用zookeeper在分布式環(huán)境下生成全局唯一ID。做法如下:每一個生成一個新ID時,創(chuàng)建一個持久順序節(jié)點,創(chuàng)建操作返回的節(jié)點序號,及微信ID,然后把比自己節(jié)點小的刪除即可。
1.3 zookeeper的設計目標
zookeeper致力于為分布式應用提供一個高性能,高可用,具有嚴格順序訪問控制能力的分布式協(xié)調(diào)服務。
高性能
zookeeper將全量數(shù)據(jù)存儲在內(nèi)存中,并直接發(fā)起與客戶端的所有非事務請求,尤其適合用于以讀為主的應用場景。
高可用
zookeeper一般以集群的方式對外提供服務,一般3-5臺機器就可以組成一個可用的zookeeper集群,每一臺機器都會在內(nèi)存中維護當前的服務器狀態(tài),并且每臺機器之間都相互保持著通信。只要集群中超過一旦的機器都在工作,那么這個集群就能夠正常對外服務;
嚴格訪問數(shù)據(jù)
對于客戶端的每一個更新請求,Zookeeper都會分配一個全局唯一的遞增編號,這個編號反映了所有事物操作的先后順序。
二、Zookeeper的數(shù)據(jù)模型
2.1. zookeeper數(shù)據(jù)結(jié)構(gòu)
Zookeeper數(shù)據(jù)模型的結(jié)構(gòu)與Unix文件系統(tǒng)很類似,整體上可以看作是一顆樹,每一個節(jié)點稱做一個ZNode。每一個Znode默認能夠存儲1MB的數(shù)據(jù),每個ZNode都可以通過其路徑唯一標識。
如何來描述一個ZNode呢?一個znode大體上分為3部分:
節(jié)點的數(shù)據(jù):即znode data(節(jié)點path,節(jié)點data的關(guān)系)就像是java map中(key,value)的關(guān)系
節(jié)點的子節(jié)點children
節(jié)點的狀態(tài)stat:用來描述當前節(jié)點的創(chuàng)建,修改記錄,包括cZxid、ctime等。
2.2 zookeeper節(jié)點類型
zookeeper中的節(jié)點有兩種類型,一種是臨時節(jié)點和永久節(jié)點。節(jié)點類型在創(chuàng)建時即被確定,并且不能改變。
臨時節(jié)點 :該節(jié)點的生命周期依賴于創(chuàng)建他們的會話。一旦會話(Session)結(jié)束,臨時節(jié)點將會被自動刪除,當然可以手動的進行刪除。雖然每個臨時的ZNode都會綁定到一個客戶端回話,但他們對所有的客戶端還是可見的。另外,Zookeeper的臨時節(jié)點不允許擁有子節(jié)點。
持久化節(jié)點:該節(jié)點的生命周期不依賴于花花,并且只有在客戶點顯示執(zhí)行刪除操作的時候,他們才能被刪除。
2.3 zookeeper 單機安裝
當前測試系統(tǒng)環(huán)境centos7.3
在centos中使用root用戶創(chuàng)建zookeeper用戶,用戶名:zookeeper 密碼:zookeeper
useradd zookeeper
passwd zookeeper
zookeeper 底層依賴jdk,zookeeper用戶登錄后,根目錄下先進行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準備配置文件
//進入conf目錄
cd /root/apps/zookeeper/zookeeper-3.4.14/conf
//復制配置文件
cp zoo_sample.cfg zoo.cfg
//zookeeper根目錄下新建data目錄
mkdir data
// vi 修改配置文件中的dataDir
// 此路徑用于存儲zookeeper中數(shù)據(jù)的內(nèi)存快照,及事務日志文件
dataDir=/root/apps/zookeeper/zookeeper-3.4.14/data
6. zookeeper啟動命令
[root@centos ~]# systemctl stop firewalld #關(guān)閉防火墻的命令
[root@centos ~]# zkServer.sh start #啟動
[root@centos ~]# zkServer.sh stop #關(guān)閉
[root@centos ~]# zkServer.sh status #查看運行狀態(tài)
啟動客戶端:
[root@localhost ~]# zkCli.sh //啟動客戶端
[zk: localhost:2181(CONNECTED) 0] ls / #查看根節(jié)點命令
//查看zookeeper進程是否存在
[root@centos zookeeper-3.4.14]# ps -ef | grep zookeeper
三、zookeeper常用的Shell命令
3.1 新增節(jié)點
create [-s] [-e] path data # 其中 -s 為有序節(jié)點, -e 臨時節(jié)點
創(chuàng)建持久化節(jié)點并寫入數(shù)據(jù):
create /hadoop "123456"
創(chuàng)建持久化有序節(jié),此時創(chuàng)建的節(jié)點名為指定節(jié)點名+自增序號
//創(chuàng)建一個持久化節(jié)點
[zk: localhost:2181(CONNECTED) 1] create /hadoop "123456"
//通過get命令獲取該節(jié)點的值
[zk: localhost:2181(CONNECTED) 2] get /hadoop
//創(chuàng)建一個有序的節(jié)點
[zk: localhost:2181(CONNECTED) 4] create -s /a "aa"
Created /a0000000001
//獲取路徑的值
[zk: localhost:2181(CONNECTED) 5] get /a0000000001
aa
//創(chuàng)建臨時節(jié)點并獲取值
[zk: localhost:2181(CONNECTED) 1] create -e /tmp "tmp"
Created /tmp
[zk: localhost:2181(CONNECTED) 2] get /tmp
tmp
創(chuàng)建臨時節(jié)點,臨時節(jié)點會在回話過期后被刪除;
[zk: localhost:2181(CONNECTED) 1] create -e /tmp "tmp"
Created /tmp
創(chuàng)建臨時有序節(jié)點,臨時節(jié)點會在會話過期后被刪除:
[zk: localhost:2181(CONNECTED) 1] create -s -e /tmp "tmp"
Created /tmp000000001
3.2 更新節(jié)點
//使用set命令來更新hadoop節(jié)點
[zk: localhost:2181(CONNECTED) 1] set /hadoop "345"
//根據(jù)版本號來更新節(jié)點
[zk: localhost:2181(CONNECTED) 1] set /hadoop "345" 2
也可以基于版本號來進行更改,此時類似于樂觀鎖機制,當你傳入的數(shù)據(jù)版本號(dataVersion)和當前節(jié)點的數(shù)據(jù)版本號不符合時,zookeeper會拒絕本次修改:
3.3 刪除節(jié)點
刪除節(jié)點的命令如下
delete path [version]
和更新節(jié)點數(shù)據(jù)一樣,也可以傳入版本號,當你傳入的數(shù)據(jù)版本號(dataVersion)和當前節(jié)點的數(shù)據(jù)版本號不符合時,zookeeper不會執(zhí)行刪除操作。
//根據(jù)版本號來刪除節(jié)點
[zk: localhost:2181(CONNECTED) 1] set /hadoop "345" 2
要想刪除某個節(jié)點及其所有后代節(jié)點,可以使用遞歸刪除,命令為 rmr path。
3.4 查看節(jié)點
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é)點各個屬性如下表。其中一個重要的概念是Zxid(ZooKeeper Transaction Id),ZooKeeper節(jié)點的每一個更改都具唯一的Zxid,如果Zxid1小于Zxid2,則Zxid1的更改發(fā)生在Zxid2更改之前。
3.5 查看節(jié)點狀態(tài)
可以使用stat命令查看節(jié)點狀態(tài),它的返回值和get命令類似,但不會返回節(jié)點數(shù)據(jù)
//使用stat命令來查看節(jié)點狀態(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é)點列表
查看節(jié)點列表有l(wèi)s path 和ls2 path 兩個命令,后者是前者的增強。不僅可以查看指定路徑下的所有節(jié)點,還可以查看當前幾點的信息
[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)聽器get path [watch]
使用get path [watch] 注冊的監(jiān)聽器能夠在節(jié)點內(nèi)容發(fā)生改變的時候,向客戶點發(fā)出通知。需要注意的是zookeeper的觸發(fā)器是一次性的(One-time trigger),觸發(fā)一次后就會立即失效。
[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)聽器stat path [watch]
使用stat path [watch] 注冊的監(jiān)聽器能夠在節(jié)點抓哪個臺發(fā)生改變的時候,向客戶點發(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)聽器ls\ls2 path [watch]
使用 ls path [watch] 或者 ls2 path [watch] 注冊的監(jiān)聽器能夠監(jiān)聽該節(jié)點下所有子節(jié)點的增加和刪除操作。
四、zookeeper權(quán)限控制
4.1 概述
zookeeper類似于文件系統(tǒng),client可以創(chuàng)建節(jié)點,更新節(jié)點,刪除節(jié)點,那么如何做到節(jié)點的權(quán)限的控制呢?zookeeper的access control list 訪問控制列表可以連接到這一點。acl權(quán)限控制,使用scheme:id:permission來表示,主要涵蓋3個方面:
權(quán)限模式(scheme):授權(quán)的策略
授權(quán)對象(id):授權(quán)的對象
權(quán)限(permission):授予的權(quán)限 其特性如下:
zookeeper的權(quán)限控制是基于每個znode節(jié)點的,需要對每個節(jié)點設置權(quán)限
每個znode支持設置多種權(quán)限控制方案和多個權(quán)限
子節(jié)點不會繼承父節(jié)點的權(quán)限,客戶點無權(quán)訪問某個節(jié)點,但可能可以訪問他的子節(jié)點
setAcl /test2 ip:192.168.60.130:rewda //將節(jié)點權(quán)限設置為Ip:19
2.168.60.130的客戶端可以對節(jié)點進行增、刪、改、查、權(quán)限管理
4.2 權(quán)限模式
采用何種方式授權(quán)
4.3 授權(quán)的對象
給誰授權(quán) 授權(quán)對象ID是指,權(quán)限賦予的實體例如:ip地址或用戶。
4.4 授予的權(quán)限
授予什么權(quán)限
create、delete、read、writer、admin也就是增、刪、改、查、管理權(quán)限,這5種權(quán)限簡寫為cdrwa、注意:這5種權(quán)限中,delete是指對子節(jié)點的刪除權(quán)限,其他4種權(quán)限只()對自身節(jié)點的權(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方式對所有用戶進行授權(quán)
: cdrwa #增、刪、改、查、管理
[zk: localhost:2181(CONNECTED) 3]
IP 授權(quán)模式 命令
#需要兩臺機器來進行連接 192.168.60.129 192.168.60.130
#使用 192.168.60.129 登錄zookeeper
zkCli.sh -server 192.168.60.130
#使用本機 192.168.60.130 zookeeper
zkCli.sh -server 192.168.60.130
Auth授權(quán)模式 命令
addauth digest <user>:<password> #添加認證用戶
setAcl <path>auth:<user>:<acl>
案例
Digest 授權(quán)模式 命令
setAcl <path> digest:<user>:<password>:<acl>
這里的密碼是經(jīng)過SHA1及BASE64處理的密文,在SHEEL中可以通過命令計算:
echo -n <user>:<password> | openssl dgst -binary -sha1 | openssl base64
先來計算一個密文
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):同一個節(jié)點可以同時使用多種模式授權(quán)
[zk: localhost:2181(CONNECTED) 8] create /hadoop4 "hadoop4"
Created /hadoop4
//添加認證用戶
[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 超級管理員
zookeeper的權(quán)限管理模式有一種叫做super,該模式提供一個超級管理員,可以訪問任何權(quán)限的節(jié)點
假設這個超級管理員是:super:admin,需要先為超級管理員生成密碼的密文
echo -n super:admin | openssl dgst -binary -sha1 | openssl base64
那么打開zookeeper目錄下的/bin/zkServer.sh 服務器腳本,找到如下一行:
之后啟動zookeeper,輸入如下的命令添加權(quán)限
addauth digest super:admin #添加認證用戶
作者:教你學懂大數(shù)據(jù)
歡迎關(guān)注微信公眾號 :教你學懂大數(shù)據(jù)