一、Zookeeper概述
1碉熄、概述
Zookeeper 是一個(gè)開(kāi)源的為分布式框架提供協(xié)調(diào)服務(wù)的 Apache 項(xiàng)目桨武。在分布式系統(tǒng)中,扮演注冊(cè)中心的角色锈津。
Zookeeper數(shù)據(jù)模型的結(jié)構(gòu)與Linux文件系統(tǒng)很像呀酸,整體上可以看做一棵樹(shù),從根節(jié)點(diǎn)往下琼梆,每個(gè)節(jié)點(diǎn)稱(chēng)為ZNode性誉。每一個(gè)ZNode默認(rèn)能夠存儲(chǔ)1MB的數(shù)據(jù),每個(gè)ZNode都對(duì)應(yīng)一個(gè)唯一的路徑茎杂,類(lèi)似于Linux中的文件路徑错览。
Zookeeper從設(shè)計(jì)模式角度來(lái)理解:是一個(gè)基于觀察者模式設(shè)計(jì)的分布式服務(wù)管理框架,它負(fù)責(zé)存儲(chǔ)和管理大家都關(guān)心的數(shù)據(jù)煌往,然后接受觀察者的注冊(cè)倾哺,一旦這些數(shù)據(jù)的狀態(tài)發(fā)生變化,Zookeeper就 將負(fù)責(zé)通知已經(jīng)在Zookeeper上注冊(cè)的那些觀察者刽脖,做出相應(yīng)的反應(yīng)悼粮。
2、特點(diǎn)
(1)Zookeeper:一個(gè)領(lǐng)導(dǎo)者(Leader)曾棕,多個(gè)跟隨者(Follower)組成的集群扣猫。
(2)集群中只要有半數(shù)以上節(jié)點(diǎn)存活,Zookeeper集群就能正常提供服務(wù)翘地。所以Zookeeper集群適合安裝奇數(shù)臺(tái)服務(wù)器申尤。
(3)全局?jǐn)?shù)據(jù)一致:每個(gè)Server保存一份相同的數(shù)據(jù)副本癌幕,Client無(wú)論連接到哪個(gè)Server,數(shù)據(jù)都是一樣的昧穿。
(4)更新請(qǐng)求順序執(zhí)行勺远,來(lái)自同一個(gè)Client的更新請(qǐng)求按其發(fā)送順序依次執(zhí)行。
(5)數(shù)據(jù)更新具有原子性时鸵,一次更新要么成功要么失敗胶逢。
(6)實(shí)時(shí)性,在一定時(shí)間范圍內(nèi)饰潜,Client能讀到最新數(shù)據(jù)初坠。
3、應(yīng)用場(chǎng)景
Zookeeper能提供的服務(wù)包括:統(tǒng)一命名服務(wù)彭雾、統(tǒng)一配置管理碟刺、統(tǒng)一集群管理、服務(wù)器節(jié)點(diǎn)動(dòng)態(tài)上下線薯酝、軟負(fù)載均衡等半沽。
(1)統(tǒng)一命名服務(wù)
在分布式環(huán)境下,經(jīng)常需要對(duì)應(yīng)用或者服務(wù)進(jìn)行統(tǒng)一命名吴菠,便于識(shí)別者填。例如IP和域名的對(duì)應(yīng)關(guān)系,一般我們都是輸入域名即可訪問(wèn)對(duì)應(yīng)網(wǎng)站做葵,但其實(shí)內(nèi)部使用DNS把域名解析成了對(duì)應(yīng)的IP地址占哟。
(2)統(tǒng)一配置管理
在分布式系統(tǒng)中,一個(gè)集群里各個(gè)服務(wù)器的配置文件在修改后經(jīng)常需要進(jìn)行同步蜂挪,手動(dòng)同步容易出錯(cuò)并且耗時(shí)耗力重挑,利用Zookeeper監(jiān)聽(tīng)的功能嗓化,可以很好的實(shí)現(xiàn)這個(gè)功能棠涮。
可以將共同的配置文件寫(xiě)入Zookeeper的一個(gè)節(jié)點(diǎn)中,然后各個(gè)Client監(jiān)聽(tīng)這個(gè)節(jié)點(diǎn)刺覆,一旦節(jié)點(diǎn)中的內(nèi)容發(fā)生變化時(shí)严肪,Zookeeper就通知各個(gè)Client。
(3)統(tǒng)一集群管理
分布式環(huán)境中谦屑,實(shí)時(shí)監(jiān)控節(jié)點(diǎn)的狀態(tài)是很有必要的驳糯,這樣可以依據(jù)節(jié)點(diǎn)的狀態(tài)動(dòng)態(tài)的做出一些調(diào)整∏獬龋可以將節(jié)點(diǎn)信息寫(xiě)入Zookeeper的ZNode中酝枢,然后監(jiān)聽(tīng)這個(gè)ZNode就可以獲取它的實(shí)時(shí)狀態(tài)變化了。
(4)服務(wù)器動(dòng)態(tài)上下線通知
這個(gè)第一小節(jié)就講了悍手。
(5)軟負(fù)載均衡
在Zookeeper中記錄每臺(tái)服務(wù)器的訪問(wèn)數(shù)帘睦,這樣有新的客戶(hù)端請(qǐng)求到來(lái)時(shí)袍患,可以讓訪問(wèn)數(shù)最少的服務(wù)器處理請(qǐng)求。
二竣付、Zookeeper安裝配置啟動(dòng)
1诡延、安裝
進(jìn)入下載地址,選擇對(duì)應(yīng)的版本下載
下載后放到Linux某個(gè)目錄下解壓即可古胆。
2肆良、配置
解壓完畢后,來(lái)到zookeeper文件夾conf目錄下拷貝一份配置文件逸绎,命名為zoo.cfg
將dataDir的目錄修改成自定義的目錄惹恃,因?yàn)?tmp目錄下的文件容易被清理掉。
除了dataDir桶良,上面還有幾個(gè)配置項(xiàng)如下:
(1)tickTime座舍,默認(rèn)2000ms。通信心跳時(shí)間陨帆,即客戶(hù)端和服務(wù)器或者服務(wù)器和服務(wù)器之間2s會(huì)發(fā)送一次心跳曲秉,檢測(cè)機(jī)器的工作狀態(tài)是否正常。
(2)initLimit疲牵,默認(rèn)10次承二。LF初始通信時(shí)限,即集群中的FL(Follow和Leader)服務(wù)器之間初始連接時(shí)能容忍的最多心跳數(shù)(tickTime的數(shù)量)纲爸。
(3)syncLimit亥鸠,默認(rèn)5次。LF同步通信時(shí)限识啦,即集群中的FL(Follow和Leader)服務(wù)器之間一次請(qǐng)求和響應(yīng)能容忍的最大心跳數(shù)负蚊。LF之間如果通信時(shí)間超過(guò)syncLimit * tickTime,Leader則會(huì)認(rèn)為Follow出故障了颓哮,將會(huì)從服務(wù)器列表中刪除Follow家妆。
(4)dataDir,Zookeeper數(shù)據(jù)存放路徑冕茅。
(5)clientPort伤极,客戶(hù)端連接端口,默認(rèn)2181姨伤。
3哨坪、啟動(dòng)
# 可選參數(shù)
./zkServer.sh [--config <conf-dir>] {start|start-foreground|stop|restart|status|print-cmd}
# 啟動(dòng)
./zkServer.sh start
# 查看狀態(tài)
./zkServer.sh status
# 重啟
./zkServer.sh restart
# 停止
./zkServer.sh stop
# 啟動(dòng)客戶(hù)端
./zkCli.sh
# 退出客戶(hù)端
[zk: localhost:2181(CONNECTED) 3] quit
三、Zookeeper集群配置
因?yàn)閆ookeeper集群的規(guī)則是半數(shù)以上的服務(wù)器可用則這個(gè)集群可用乍楚,所以集群中最少需要3臺(tái)以上的服務(wù)器并且服務(wù)器的數(shù)量最好是奇數(shù)当编。
為什么是奇數(shù),因?yàn)樵谙嗤蒎e(cuò)能力的情況下徒溪,奇數(shù)臺(tái)服務(wù)器更節(jié)省資源。比如3臺(tái)服務(wù)器的集群,至少要2臺(tái)以上服務(wù)器正常工作這個(gè)集群才可用津畸,也就是最多允許1臺(tái)服務(wù)器宕機(jī)重父;4臺(tái)服務(wù)器的集群,至少需要3臺(tái)以上服務(wù)器正常工作這個(gè)集群才可用,也就是最多允許1臺(tái)服務(wù)器宕機(jī)。3臺(tái)或者4臺(tái)服務(wù)器的集群,都至多允許一臺(tái)服務(wù)器宕機(jī)礁凡,容錯(cuò)能力相同的情況下,4臺(tái)服務(wù)器就浪費(fèi)了一臺(tái)的數(shù)量慧妄。
另外一個(gè)原因是因?yàn)閒ollow在選舉leader的時(shí)候顷牌,要求可用節(jié)點(diǎn)數(shù)量 > 總節(jié)點(diǎn)數(shù)量 / 2。如果集群的節(jié)點(diǎn)數(shù)量為偶數(shù)臺(tái)塞淹,那么就可能出現(xiàn)無(wú)法選舉出Leader的情況窟蓝。具體參考這篇文章
簡(jiǎn)單點(diǎn),這里我們的集群中有3個(gè)節(jié)點(diǎn)饱普,即3個(gè)Zookeeper服務(wù)器运挫。
1、解壓安裝
跟上面單機(jī)一樣套耕,分別下載解壓到3臺(tái)服務(wù)器的指定目錄谁帕。
2、配置服務(wù)器編號(hào)
在服務(wù)器的zookeeper文件夾的根目錄下創(chuàng)建zkDatas文件夾冯袍,并在zkDatas文件夾下創(chuàng)建一個(gè)myid的文件匈挖,在文件中添加server對(duì)應(yīng)的編號(hào),集群中唯一康愤。
cd /usr/local/apache-zookeeper-3.5.7
mkdir zkDatas
cd zkDatas
vi myid
## 服務(wù)器1的myid文件內(nèi)容如下儡循,對(duì)應(yīng)的,服務(wù)器2的myid內(nèi)容為2征冷,服務(wù)器3的myid內(nèi)容為3
1
3择膝、配置zoo.cfg文件
配置三個(gè)服務(wù)器的zoo.cfg文件內(nèi)容如下
# 拷貝zoo_sample.cfg文件
cp -r zoo_sample.cfg zoo.cfg
vi zoo.cfg
## zoo.cfg文件內(nèi)容如下
dataDir=/usr/local/apache-zookeeper-3.5.7/zkDatas
#######################cluster##########################
server.1=192.168.1.128:2888:3888
server.2=192.168.1.129:2888:3888
server.3=192.168.1.130:2888:3888
關(guān)于上面集群的配置server.A=B:C:D
解釋如下
- A是一個(gè)數(shù)字,表示第幾號(hào)服務(wù)器资盅。之前我們配置了myid文件调榄,A的值就是myid文件中的值踊赠。zookeeper在啟動(dòng)的時(shí)候會(huì)讀取此文件呵扛,拿到里面的文件內(nèi)容后再和zoo.cfg文件里的配置進(jìn)行比較,判斷是哪個(gè)服務(wù)器筐带。
- B代表服務(wù)器的地址今穿。
- C是Leader和Follow交換信息的端口。
- D是當(dāng)集群中的Leader服務(wù)器歇逼的時(shí)候伦籍,重新選舉時(shí)的通信端口蓝晒。
4腮出、啟動(dòng)各個(gè)服務(wù)器
啟動(dòng)完后,就會(huì)告訴你誰(shuí)是leader誰(shuí)是follow芝薇。
[root@localhost apache-zookeeper-3.5.7]# bin/zkServer.sh status
JMX enabled by default
Using config: /usr/local/apache-zookeeper-3.5.7/bin/../conf/zoo.cfg
Mode: follower
[root@localhost apache-zookeeper-3.5.7]# bin/zkServer.sh status
JMX enabled by default
Using config: /usr/local/apache-zookeeper-3.5.7/bin/../conf/zoo.cfg
Mode: leader
[root@localhost apache-zookeeper-3.5.7]# bin/zkServer.sh status
JMX enabled by default
Using config: /usr/local/apache-zookeeper-3.5.7/bin/../conf/zoo.cfg
Mode: follower
四胚嘲、Zookeeper的選舉機(jī)制
單機(jī)模式下不涉及選舉,只有在集群模式下才會(huì)進(jìn)行選舉洛二。Leader選舉一般發(fā)生在下面兩種情況:第一次啟動(dòng)集群的時(shí)候和集群運(yùn)行過(guò)程中Leader掛了馋劈。這兩種情況下Leader的選舉機(jī)制時(shí)不同的,需要分開(kāi)討論晾嘶。
在學(xué)習(xí)選舉機(jī)制之前妓雾,需要先學(xué)習(xí)幾個(gè)概念。
- SID:服務(wù)器ID垒迂,即myid文件中的值械姻,用來(lái)唯一標(biāo)識(shí)一臺(tái)Zookeeper集群中的機(jī)器,不能重復(fù)机断。
- ZXID:zookeeper transaction id楷拳,即zookeeper事務(wù)id,用來(lái)標(biāo)識(shí)一次服務(wù)器狀態(tài)的變更吏奸。在某一時(shí)刻唯竹,集群中每臺(tái)機(jī)器的zxid大概率是不同的。
- Epoch:邏輯時(shí)鐘苦丁,也叫投票的次數(shù)浸颓,每投完一次票這個(gè)值就會(huì)增加,同一輪投票過(guò)程中邏輯時(shí)鐘的值是相同的旺拉。
1产上、第一次啟動(dòng)時(shí)的選舉機(jī)制
(1)server1啟動(dòng)后,發(fā)起一次選舉蛾狗。server1投自己一票晋涣,此時(shí)server1共有1票,不夠半數(shù)以上(3票)沉桌,無(wú)法產(chǎn)生Leader谢鹊,server1狀態(tài)保持LOOKING。
(2)server2啟動(dòng)留凭,發(fā)起一次選舉佃扼。server1和server2各投自己一票并交換選票信息,此時(shí)server1發(fā)現(xiàn)server2的SID比自己目前投票的(也就是它自身)更大蔼夜,于是更改投票為server2兼耀。此時(shí)server1共有0票,server2共有2票,不夠半數(shù)以上瘤运,無(wú)法產(chǎn)生leader窍霞,server1和server2狀態(tài)保持LOOKING。
(3)server3啟動(dòng)拯坟,發(fā)起一次選舉但金。和(2)一樣,server1和server2最終都會(huì)把票投給server3郁季,那么此時(shí)server1和server2的票數(shù)就為0傲绣,而server3的票數(shù)為3,超過(guò)了半數(shù)巩踏,server3變成leader秃诵。server1和server2更改狀態(tài)為FOLLOWING,server3更改狀態(tài)為L(zhǎng)EADING塞琼。
(4)server4啟動(dòng)菠净,發(fā)起一次選舉。此時(shí)server1和server2都不是LOOKING狀態(tài)彪杉,所以不會(huì)更改選票信息毅往,所以最終server4少數(shù)服從多數(shù),把選票投給server3派近,此時(shí)server3總票數(shù)為4攀唯,其他三臺(tái)服務(wù)器總票數(shù)都為0。
(5)server4啟動(dòng)渴丸,發(fā)起一次選舉侯嘀。和(4)一樣的流程。
2谱轨、非第一次啟動(dòng)時(shí)的選舉機(jī)制
當(dāng)集群中出現(xiàn)下面的情況時(shí)戒幔,會(huì)觸發(fā)leader選舉機(jī)制
(1)集群運(yùn)行過(guò)程中,有新的服務(wù)器節(jié)點(diǎn)加入土童。
(2)follow服務(wù)器無(wú)法和leader服務(wù)器通信時(shí)诗茎,follow會(huì)認(rèn)為leader掛了。
當(dāng)觸發(fā)選舉機(jī)制時(shí)献汗,集群可能存在兩種情況
(1)集群中此時(shí)已經(jīng)存在leader敢订。那么在這種情況下,只需要告訴發(fā)起選舉的服務(wù)器有關(guān)leader的相關(guān)信息罢吃,讓該服務(wù)器和leader建立連接并進(jìn)行狀態(tài)同步即可楚午。
(2)集群中此時(shí)不存在leader。
還是用上一小節(jié)的圖來(lái)說(shuō)刃麸,集群中5臺(tái)server醒叁,SID分別是1,2,3,4,5司浪,ZXID分別是8,8,8,7,7泊业,server3是leader把沼。此時(shí)server3和server5掛了,follow服務(wù)器都會(huì)把自己的狀態(tài)變成LOOKING吁伺,開(kāi)始進(jìn)行l(wèi)eader選舉饮睬。
這里就需要用到上面說(shuō)過(guò)的三個(gè)概念:Epoch、SID和ZXID篮奄。選舉Leader規(guī)則:
- Epoch大的直接勝出
- Epoch相同捆愁,ZXID大的勝出
- ZXID相同,SID大的勝出
對(duì)于剩下的server1窟却、server2和server4昼丑,它們的(Epoch, ZXID, SID)的值分別是(1, 8, 1)、(1, 8, 2)夸赫、(1, 7, 4)菩帝。所以最后的leader就是server2。
五茬腿、客戶(hù)端相關(guān)的命令
# 啟動(dòng)客戶(hù)端
./zkCli.sh
# help命令呼奢,可以顯式所有的操作命令
[zk: localhost:2181(CONNECTED) 0] help
一些比較常見(jiàn)的如下
(1)ls [-s] [-w] [-R] path
,查看對(duì)應(yīng)path下的子節(jié)點(diǎn)切平,-w
表示監(jiān)聽(tīng)子節(jié)點(diǎn)變化握础,-s
附加次級(jí)信息。
(2)create path
悴品,在對(duì)應(yīng)path下創(chuàng)建一個(gè)節(jié)點(diǎn)禀综,-s
表示節(jié)點(diǎn)帶序號(hào),-e
表示創(chuàng)建臨時(shí)節(jié)點(diǎn)苔严,重啟后或者超時(shí)就會(huì)被刪除菇存。
(3)get path
,獲得節(jié)點(diǎn)的值(可監(jiān)聽(tīng))邦蜜。-w
表示監(jiān)聽(tīng)節(jié)點(diǎn)內(nèi)容變化依鸥,-s
表示附加次級(jí)信息。
(4)set path data
悼沈,設(shè)置節(jié)點(diǎn)的具體值贱迟。
(5)stat path
,查看節(jié)點(diǎn)狀態(tài)絮供。
(6)delete path
衣吠,刪除節(jié)點(diǎn)。
(7)deleteall path
壤靶,遞歸刪除節(jié)點(diǎn)缚俏。
1、查看ZNode節(jié)點(diǎn)信息
[zk: localhost:2181(CONNECTED) 4] ls /
[zookeeper]
[zk: localhost:2181(CONNECTED) 5] 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
ls -s path
可以查看節(jié)點(diǎn)的詳細(xì)數(shù)據(jù)。
(1)cZxid:創(chuàng)建節(jié)點(diǎn)的事務(wù)id
每次修改 ZooKeeper 狀態(tài)都會(huì)產(chǎn)生一個(gè) ZooKeeper 事務(wù) ID忧换。事務(wù) ID 是 ZooKeeper 中所有修改總的次序恬惯。每次修改都有唯一的 zxid,如果 zxid1 小于 zxid2亚茬,那么 zxid1 在 zxid2 之前發(fā)生酪耳。
(2)ctime:znode 被創(chuàng)建的毫秒數(shù)(從 1970 年開(kāi)始)
(3)mZxid:znode 最后更新的事務(wù) zxid
(4)mtime:znode 最后修改的毫秒數(shù)(從 1970 年開(kāi)始)
(5)pZxid:znode 最后更新的子節(jié)點(diǎn) zxid
(6)cversion:znode 子節(jié)點(diǎn)變化號(hào),znode 子節(jié)點(diǎn)修改次數(shù)
(7)dataVersion:znode 數(shù)據(jù)變化號(hào)
(8)aclVersion:znode 訪問(wèn)控制列表的變化號(hào)
(9)ephemeralOwner:如果是臨時(shí)節(jié)點(diǎn)刹缝,這個(gè)是 znode 擁有者的 session id碗暗。如果不是臨時(shí)節(jié)點(diǎn)則是 0
(10)dataLength:znode 的數(shù)據(jù)長(zhǎng)度
(11)numChildren:znode 子節(jié)點(diǎn)數(shù)量
2、創(chuàng)建ZNode節(jié)點(diǎn)
Zookeeper中節(jié)點(diǎn)類(lèi)型可以大致分為兩類(lèi)持久化(Persistent)節(jié)點(diǎn)和臨時(shí)(Ephemeral)節(jié)點(diǎn)梢夯,又可以細(xì)分為四類(lèi):
(1)持久化目錄節(jié)點(diǎn)
客戶(hù)端與Zookeeper斷開(kāi)連接后言疗,該節(jié)點(diǎn)依舊存在。
(2)持久化順序編號(hào)目錄節(jié)點(diǎn)
客戶(hù)端與Zookeeper斷開(kāi)連接后颂砸,該節(jié)點(diǎn)依舊存在洲守,只是Zookeeper給該節(jié)點(diǎn)名稱(chēng)進(jìn)行順序編號(hào)。
(3)臨時(shí)目錄節(jié)點(diǎn)
客戶(hù)端與Zookeeper斷開(kāi)連接后沾凄,該節(jié)點(diǎn)被刪除梗醇。
(4)臨時(shí)順序編號(hào)目錄節(jié)點(diǎn)
客戶(hù)端與 Zookeeper 斷開(kāi)連接后,該節(jié)點(diǎn)被刪除撒蟀,只是Zookeeper給該節(jié)點(diǎn)名稱(chēng)進(jìn)行順序編號(hào)叙谨。
創(chuàng)建znode時(shí)設(shè)置順序標(biāo)識(shí),znode名稱(chēng)后會(huì)附加一個(gè)值保屯,順序號(hào)是一個(gè)單調(diào)遞增的計(jì)數(shù)器手负,由父節(jié)點(diǎn)維護(hù)。
注意:在分布式系統(tǒng)中姑尺,順序號(hào)可以被用于為所有的事件進(jìn)行全局排序竟终,這樣客戶(hù)端可以通過(guò)順序號(hào)推斷事件的順序。
2.1 創(chuàng)建不帶序號(hào)的永久節(jié)點(diǎn)
[zk: localhost:2181(CONNECTED) 14] create /znode1 "value1"
Created /znode1
[zk: localhost:2181(CONNECTED) 15] create /znode2 "value2"
Created /znode2
# 獲得節(jié)點(diǎn)的值
[zk: localhost:2181(CONNECTED) 16] get -s /znode1
value1
cZxid = 0x6
ctime = Sat Dec 04 18:43:50 CST 2021
mZxid = 0x6
mtime = Sat Dec 04 18:43:50 CST 2021
pZxid = 0x6
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 6
numChildren = 0
2.2 創(chuàng)建帶序號(hào)的永久節(jié)點(diǎn)
[zk: localhost:2181(CONNECTED) 17] create -s /znode1/znode3 "value3"
Created /znode1/znode30000000000
[zk: localhost:2181(CONNECTED) 18] create -s /znode1/znode4 "value4"
Created /znode1/znode40000000001
[zk: localhost:2181(CONNECTED) 19] create -s /znode5 "value5"
Created /znode50000000003
[zk: localhost:2181(CONNECTED) 20] create -s /znode1/znode6 "value6"
Created /znode1/znode60000000002
可以發(fā)現(xiàn)如果原來(lái)沒(méi)有序號(hào)節(jié)點(diǎn)切蟋,序號(hào)從 0 開(kāi)始依次遞增统捶。如果原節(jié)點(diǎn)下已有 2 個(gè)節(jié)點(diǎn),則再排序時(shí)從 2 開(kāi)始柄粹,以此類(lèi)推喘鸟。
2.3 創(chuàng)建臨時(shí)節(jié)點(diǎn)
[zk: localhost:2181(CONNECTED) 21] create -e /znode2/znode7 "value7"
Created /znode2/znode7
[zk: localhost:2181(CONNECTED) 22] create -e -s /znode2/znode8 "value8"
Created /znode2/znode80000000001
[zk: localhost:2181(CONNECTED) 23] ls /znode2
[znode7, znode80000000001]
# 重啟客戶(hù)端數(shù)據(jù)消失
2.4 修改節(jié)點(diǎn)的值
[zk: localhost:2181(CONNECTED) 24] set /znode2/znode7 "val"
[zk: localhost:2181(CONNECTED) 25] get /znode2/znode7
val
3、監(jiān)聽(tīng)節(jié)點(diǎn)
3.1 監(jiān)聽(tīng)器原理
客戶(hù)端注冊(cè)監(jiān)聽(tīng)它關(guān)心的目錄節(jié)點(diǎn)驻右,當(dāng)目錄節(jié)點(diǎn)發(fā)生變化時(shí)(數(shù)據(jù)改變什黑、節(jié)點(diǎn)刪除、子目錄節(jié)點(diǎn)增加刪除)堪夭,Zookeeper會(huì)通知客戶(hù)端愕把。
(1)首先要有一個(gè)main()線程拣凹。
(2)在main線程中創(chuàng)建zookeeper客戶(hù)端,這時(shí)就會(huì)創(chuàng)建兩個(gè)線程恨豁,一個(gè)負(fù)責(zé)網(wǎng)絡(luò)連接通信(connect)嚣镜,一個(gè)負(fù)責(zé)監(jiān)聽(tīng)(listener)。
(3)通過(guò)connect線程將注冊(cè)的監(jiān)聽(tīng)事件發(fā)送給zookeeper圣絮。
(4)將監(jiān)聽(tīng)事件添加到zookeeper的注冊(cè)監(jiān)聽(tīng)列表中祈惶。
(5)zookeeper監(jiān)聽(tīng)到有數(shù)據(jù)或路徑變化時(shí)雕旨,就會(huì)通知listener線程扮匠。
(6)listener線程內(nèi)部調(diào)用process方法。
3.2 常見(jiàn)的監(jiān)聽(tīng)
(1)監(jiān)聽(tīng)節(jié)點(diǎn)數(shù)據(jù)的變化:get -w path
(2)監(jiān)聽(tīng)子節(jié)點(diǎn)增減的變化:ls -w path
注意:上面兩種監(jiān)聽(tīng)都是注冊(cè)一次生效一次凡涩。如果想要多次生效棒搜,那么就要注冊(cè)多次。
4活箕、刪除和查看節(jié)點(diǎn)
# 查看/znode2下的子節(jié)點(diǎn)
[zk: localhost:2181(CONNECTED) 1] ls /znode2
[znode7, znode80000000001]
# 刪除/znode2節(jié)點(diǎn)力麸,因?yàn)橄旅娲嬖谧庸?jié)點(diǎn),所以不能刪除
[zk: localhost:2181(CONNECTED) 2] delete /znode2
Node not empty: /znode2
# 刪除/znode2/znode80000000001節(jié)點(diǎn)
[zk: localhost:2181(CONNECTED) 3] delete /znode2/znode80000000001
[zk: localhost:2181(CONNECTED) 4] ls /znode2
[znode7]
[zk: localhost:2181(CONNECTED) 5] delete /znode2
Node not empty: /znode2
# 刪除/znode2及其下面所有子節(jié)點(diǎn)
[zk: localhost:2181(CONNECTED) 6] deleteall /znode2
[zk: localhost:2181(CONNECTED) 7] ls /znode2
Node does not exist: /znode2
# 查看節(jié)點(diǎn)狀態(tài)
[zk: localhost:2181(CONNECTED) 9] stat /znode1
cZxid = 0x6
ctime = Sat Dec 04 18:43:50 CST 2021
mZxid = 0x6
mtime = Sat Dec 04 18:43:50 CST 2021
pZxid = 0xb
cversion = 3
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 6
numChildren = 3
六育韩、客戶(hù)端相關(guān)的API
除了在啟動(dòng)zkCli.sh在命令行中使用相關(guān)的命令克蚂,也可以使用編程語(yǔ)言操作zookeeper相關(guān)的api。
首先創(chuàng)建一個(gè)Java的maven項(xiàng)目筋讨,在pom.xml文件中引入zookeeper相關(guān)的依賴(lài)
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.5</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
zookeeper相關(guān)的api可以參考官方文檔:點(diǎn)擊鏈接
為了便于測(cè)試埃叭,可以引入junit的依賴(lài)
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
</dependency>
client寫(xiě)數(shù)據(jù)的時(shí)候,寫(xiě)請(qǐng)求可能是發(fā)送給Leader也可能是Follow悉罕。假設(shè)集群中有3臺(tái)服務(wù)器赤屋,1臺(tái)Leader,2臺(tái)Follow
(1)發(fā)送給Leader節(jié)點(diǎn)時(shí)
當(dāng)集群中半數(shù)以上節(jié)點(diǎn)完成write請(qǐng)求后壁袄,就開(kāi)始開(kāi)放給客戶(hù)端請(qǐng)求了类早。
(2)發(fā)送給Follow節(jié)點(diǎn)時(shí)
當(dāng)集群中半數(shù)以上節(jié)點(diǎn)完成write請(qǐng)求后,就開(kāi)始開(kāi)放給客戶(hù)端請(qǐng)求了嗜逻。
七涩僻、Zookeeper實(shí)現(xiàn)分布式鎖
可以參考之前的文章:Zookeeper + Curator實(shí)現(xiàn)分布式鎖
文章首發(fā)于我的公眾號(hào)【禿頭哥編程】,歡迎大家關(guān)注栈顷。