不懂 Zookeeper?來(lái)看看這篇文章
? 開(kāi)源Linux
長(zhǎng)按二維碼加關(guān)注~

高并發(fā)分布式開(kāi)發(fā)技術(shù)體系已然非常的龐大,從國(guó)內(nèi)互聯(lián)網(wǎng)企業(yè)使用情況,可發(fā)現(xiàn)RPC、Dubbo、ZK是最基礎(chǔ)的技能要求。關(guān)于Zookeeper你是不是還停留在Dubbo注冊(cè)中心的印象中呢?還有它的工作原理呢?經(jīng)典應(yīng)用場(chǎng)景呢?對(duì)前面三個(gè)問(wèn)題,如若回答時(shí)沒(méi)有自己的思路或者說(shuō)并未了解,那么我覺(jué)得我可以幫助到你去入門(mén),并深化這些知識(shí),讓你在面試中更好地去回答。
話不多說(shuō)進(jìn)入正題
1. 并發(fā)環(huán)境下面臨的挑戰(zhàn)
回憶我們學(xué)多線程的時(shí)候,網(wǎng)上有個(gè)圖也是十分的有意思

其實(shí)我們把線程換成進(jìn)程,相當(dāng)于每臺(tái)服務(wù)上跑了一個(gè)程序,相同的應(yīng)用程序運(yùn)行于多個(gè)服務(wù)器集群上,是為了解決單臺(tái)服務(wù)面對(duì)高并發(fā)處理不來(lái)的情況。而嘗試去處理這些情況,我們就會(huì)面臨很多諸如此類(lèi)的問(wèn)題
比如說(shuō)我們現(xiàn)在是3臺(tái)服務(wù)器的一個(gè)集群, 怎么保證所有機(jī)器共享的配置信息保持一致?
有一臺(tái)機(jī)器掛掉了,其他機(jī)器如何感知到這一變化并接管任務(wù)?
用戶量突然的爆增,需要增加機(jī)器來(lái)緩解壓力,如何做到不重啟集群而完成機(jī)器的添加?
分布式系統(tǒng),怎么高效協(xié)同多臺(tái)服務(wù)對(duì)同一網(wǎng)絡(luò)文件進(jìn)行寫(xiě)操作(網(wǎng)絡(luò)并不是即時(shí)的,它并不可靠,存在延時(shí))?
此時(shí)我們就需要一個(gè)類(lèi)似于線程協(xié)同機(jī)制的能讓進(jìn)程進(jìn)行協(xié)同的工具
2. Zookeeper的介紹
① Zookeeper的名字由來(lái)
在apache上的許多開(kāi)源項(xiàng)目都是以動(dòng)物形象作為icon,比如tomcat就是一只貓,hive是只黃蜂等,zookeeper的工作就是把這些動(dòng)物的行動(dòng)進(jìn)行協(xié)調(diào)
② Zookeeper的簡(jiǎn)介
zookeeper就是一種用于分布式應(yīng)用程序的高性能協(xié)調(diào)服務(wù),它的特點(diǎn)就是數(shù)據(jù)是存于內(nèi)存中的,持久化實(shí)現(xiàn)在日志中。它的內(nèi)存類(lèi)似于樹(shù)形結(jié)構(gòu),且高吞吐低延遲,可以幫助我們實(shí)現(xiàn)分布式統(tǒng)一配置中心,服務(wù)注冊(cè),分布式鎖等 組成ZooKeeper服務(wù)的服務(wù)器必須彼此了解。它們維護(hù)內(nèi)存中的狀態(tài)圖像,以及持久性存儲(chǔ)中的事務(wù)日志和快照。只要大多數(shù)服務(wù)器可用,ZooKeeper服務(wù)就可用。客戶端連接到單個(gè)ZooKeeper服務(wù)器。客戶端維護(hù)TCP連接,通過(guò)該連接發(fā)送請(qǐng)求,獲取響應(yīng),獲取監(jiān)視事件以及發(fā)送tick。如果與服務(wù)器的TCP連接中斷,則客戶端將連接到其他服務(wù)器。
③ Zookeeper的安裝(linux下)
1.JDK版本需要在1.6以上
2.下載:https://archive.apache.org/dist/zookeeper/zookeeper-3.5.2/zookeeper-3.5.2.tar.gz
3.解壓后的conf目錄,增加配置文件zoo.cfg
4.啟動(dòng)服務(wù)端 bin/zkServer.sh start
5.測(cè)試,客戶端連接:bin/zkCli.sh -server 127.0.0.1:2181
zoo.cfg的關(guān)鍵配置有3個(gè):
tickTime=2000:一次心跳的基本時(shí)間,
dataDir:數(shù)據(jù)與日志的存放處
clientPort:端口號(hào)
④ Zookeeper的特點(diǎn)
1.數(shù)據(jù)結(jié)構(gòu)簡(jiǎn)單
類(lèi)似于Unix文件系統(tǒng)樹(shù)形結(jié)構(gòu),每個(gè)目錄成為Znode節(jié)點(diǎn),但它不同于文件系統(tǒng),它既可以視為文件夾,也可以視為文件來(lái)存放數(shù)據(jù),但是我們平時(shí)還是得叫它節(jié)點(diǎn),別叫文件夾這么掉價(jià)。
需要注意:同一個(gè)節(jié)點(diǎn)下的子節(jié)點(diǎn)名稱不能相同,且命名是有規(guī)范的,它的路徑是沒(méi)有相對(duì)路徑的概念的,都是絕對(duì)路徑,任何開(kāi)始都以"/"開(kāi)始,最后就是,它存放數(shù)據(jù)的大小是有限制的
2.數(shù)據(jù)模型特點(diǎn)
層次命名空間:就是上面已經(jīng)提到的,類(lèi)似于unix的文件系統(tǒng),以"/"為根,節(jié)點(diǎn)可以包含關(guān)聯(lián)數(shù)據(jù)和子節(jié)點(diǎn),絕對(duì)路徑 Znode:名稱唯一,命名有規(guī)范,類(lèi)型分4種:持久,順序,臨時(shí),臨時(shí)順序,節(jié)點(diǎn)的數(shù)據(jù)構(gòu)成之后再提
3.命名規(guī)范
節(jié)點(diǎn)名稱除下列限制外,可以使用任何unicode字符:
1. null字符(\u0000)不能作為路徑名的一部分;
2. 以下字符不能使用,因?yàn)樗鼈儾荒芎芎玫仫@示,或者以令人困惑的方式呈現(xiàn):\u0001 - \u0019和\u007F - \u009F。
3. 不允許使用以下字符:\ud800 - uf8fff, \uFFF0 - uFFFF。
4. “.”字符可以用作另一個(gè)名稱的一部分,但是“.”和“..”不能單獨(dú)用于指示路徑上的節(jié)點(diǎn),因?yàn)閆ooKeeper不使用相對(duì)路徑。
下列內(nèi)容無(wú)效:“/a/b/. / c”或“c / a / b / . . /”。
5. “zookeeper”是保留節(jié)點(diǎn)名。
4.一些命令
因?yàn)槲业碾娔X是window系統(tǒng)的,所以我找了一個(gè)window版本的zookeeper來(lái)進(jìn)行演示
先大致解釋一下各個(gè)目錄的內(nèi)容
bin ---> 包括了linux和window的運(yùn)行程序的運(yùn)行目錄
conf ---> zookeeper的配置zoo.cfg
contrib ---> 其他一些組件和發(fā)行版本
dist-maven ---> maven發(fā)布下的一些jar包
docs ---> 文檔
lib ---> 庫(kù)
recipe ---> 一些應(yīng)用實(shí)例
src ---> zookeeper的源碼,因?yàn)閦ookeeper是java寫(xiě)出來(lái)的
啟動(dòng)bin目錄下的zkServer.cmd,再啟動(dòng)zkClient.cmd即可,在我根本不知道該如何進(jìn)行學(xué)習(xí)的時(shí)候,一般來(lái)說(shuō)輸入help,-help,-h這些指令就可以獲取到幫助,下圖我就是在客戶端輸入了-help指令

因?yàn)槊疃枷鄬?duì)簡(jiǎn)單所以也不進(jìn)行演示了,唯一需要注意的是要注意路徑"/"的問(wèn)題,比如 ls / 就是根目錄,create /zk 123,還有各個(gè)命令的依托條件,比如create必須要提供父節(jié)點(diǎn),delete節(jié)點(diǎn)時(shí)次節(jié)點(diǎn)不能有子節(jié)點(diǎn)等···
5.Zookeeper的重要特點(diǎn)---有序
提供多種方式跟蹤時(shí)間,ZooKeeper給每個(gè)更新貼上一個(gè)數(shù)字,這個(gè)數(shù)字反映了所有ZooKeeper事務(wù)的順序,嚴(yán)格的順序意味著可以在客戶機(jī)上實(shí)現(xiàn)復(fù)雜的同步原語(yǔ) 解釋czxid、version、zoo.cfg中ticks配置
Zxid :Zookeeper中每次寫(xiě)請(qǐng)求都對(duì)應(yīng)一個(gè)唯一的事務(wù)id,稱為 Zxid,它是全局的且有序的,如果 Zxid1 小于 Zxid2,那 Zxid1 就一定是發(fā)生在 Zxid2 前 version numbers :版本號(hào),對(duì)節(jié)點(diǎn)的寫(xiě)請(qǐng)求都會(huì)導(dǎo)致該節(jié)點(diǎn)的3種版本號(hào)增加(其實(shí)套路和樂(lè)觀鎖差不多),dataVersion(對(duì)znode數(shù)據(jù)的更改次數(shù)),cversion(對(duì)znode子節(jié)點(diǎn)的更改次數(shù)),aclVersion(對(duì)znode ACL的更改次數(shù) ticks :當(dāng)使用多服務(wù)器Zookeeper時(shí),服務(wù)器使用一個(gè)“滴答”來(lái)定義事件的時(shí)間,如狀態(tài)上傳,會(huì)話超時(shí)等,它通過(guò)最小會(huì)話超時(shí)(默認(rèn)是滴答時(shí)間x2)間接公開(kāi),如果客戶端請(qǐng)求超過(guò)這個(gè)時(shí)間,那客戶端就不再能連接上服務(wù)器端 real time:Zookeeper并不使用真實(shí)時(shí)間
你可以使用stat path或者ls2來(lái)查看這些信息

cZxid:創(chuàng)建該節(jié)點(diǎn)的zxid
ctime:該節(jié)點(diǎn)的創(chuàng)建時(shí)間
mZxid:該節(jié)點(diǎn)的最后修改zxid
mtime:該節(jié)點(diǎn)的最后修改時(shí)間
pZxid:該節(jié)點(diǎn)的最后子節(jié)點(diǎn)修改zxid
cversion:該節(jié)點(diǎn)的子節(jié)點(diǎn)變更次數(shù)
dataVersion:該節(jié)點(diǎn)數(shù)據(jù)被修改的次數(shù)
aclVersion:該節(jié)點(diǎn)的ACL變更次數(shù)
aphemeraOwner:臨時(shí)節(jié)點(diǎn)所有者會(huì)話id,非臨時(shí)的為0
dataLength:該節(jié)點(diǎn)數(shù)據(jù)長(zhǎng)度
numChildren:子節(jié)點(diǎn)數(shù)
這些數(shù)據(jù)都在從側(cè)面告訴我們,zookeeper是一個(gè)協(xié)調(diào)者
6.zookeeper的第二個(gè)特點(diǎn)---可復(fù)制
數(shù)據(jù)可復(fù)制,可備份。zookeeper可以快速地搭建一個(gè)集群,內(nèi)部自帶了這樣的一些工具與機(jī)制,我們只需要設(shè)置一些配置即可,保證服務(wù)可靠,不會(huì)成為單點(diǎn)故障

7.zookeeper的第三個(gè)特點(diǎn)---迅速
zookeeper的一些特點(diǎn)可以應(yīng)用于大型分布式系統(tǒng)

3.zookeeper的理論
① zookeeper的會(huì)話機(jī)制

Session會(huì)話
1.一個(gè)客戶端連接一個(gè)會(huì)話,由zookeeper分配唯一會(huì)話id
2.客戶端以特定的時(shí)間間隔發(fā)送心跳以保持會(huì)話有效,
3.超過(guò)會(huì)話超時(shí)時(shí)間未收到客戶端的心跳,則判斷客戶端無(wú)效(默認(rèn)2倍tickTime)
4.會(huì)話中額請(qǐng)求是FIFO(先進(jìn)先出原則)的順序執(zhí)行
② znode的數(shù)據(jù)構(gòu)成
節(jié)點(diǎn)數(shù)據(jù):存儲(chǔ)的基本信息(狀態(tài),配置,位置等)
節(jié)點(diǎn)元數(shù)據(jù):stat命令下的一些數(shù)據(jù)
數(shù)據(jù)大小:限制1M
③ znode的節(jié)點(diǎn)類(lèi)型
1.持久節(jié)點(diǎn):直接通過(guò)create path value所創(chuàng)建
2.臨時(shí)節(jié)點(diǎn):create -e path value
3.順序節(jié)點(diǎn):create -s path value
注意
1.session會(huì)話失效時(shí),臨時(shí)節(jié)點(diǎn)就會(huì)被刪除
2.順序節(jié)點(diǎn)的創(chuàng)建,后為10位十進(jìn)制序號(hào),每個(gè)父節(jié)點(diǎn)擁有一個(gè)計(jì)數(shù)器,這個(gè)計(jì)數(shù)器也是有限制的,到2147483647之后將溢出
3.順序節(jié)點(diǎn)在會(huì)話結(jié)束仍然存在
④ Watch監(jiān)聽(tīng)機(jī)制
客戶端能在znodes上設(shè)置watch,監(jiān)聽(tīng)znode的變化,包括增刪改查,通過(guò)stat path ,ls2 path get path皆可查看
觸發(fā)watch事件的條件有4種,create,delete,change,child(子節(jié)點(diǎn)事件)
watch的重要特性
1.僅一次性:watch觸發(fā)后會(huì)立即刪除,要持續(xù)監(jiān)聽(tīng)變化的話就要持續(xù)提供設(shè)置watch,這也是watch的注意事項(xiàng)
2.有序性:客戶端先得到watch通知才可查看變化結(jié)果
watch的注意事項(xiàng)
1.剛剛提及到的它的僅一次性
2.獲取事件和發(fā)送watch,獲取watch,這些請(qǐng)求有可能存在延時(shí),所以不能絕對(duì)可靠得到每個(gè)節(jié)點(diǎn)發(fā)生的每個(gè)更改
3.一個(gè)watch對(duì)象只會(huì)被通知一次,如果一個(gè)watch同時(shí)注冊(cè)了多個(gè)接口(exists,getData),如果此時(shí)刪除節(jié)點(diǎn),雖然這個(gè)事件對(duì)exists和getData都有效,但是watch只會(huì)被調(diào)用一次
阻塞線程喚醒機(jī)制—客戶端可以被動(dòng)接受其他客戶端進(jìn)程狀態(tài)通知
⑤ zookeeper的特性
1.順序一致性(Sequential Consistency),保證客戶端操作是按順序生效的;
2.原子性(Atomicity),更新成功或失敗。沒(méi)有部分結(jié)果。
3.單個(gè)系統(tǒng)映像,無(wú)論連接到哪個(gè)服務(wù)器,客戶端都將看到相同的內(nèi)容
4.可靠性,數(shù)據(jù)的變更不會(huì)丟失,除非被客戶端覆蓋修改。
5.及時(shí)性,保證系統(tǒng)的客戶端當(dāng)時(shí)讀取到的數(shù)據(jù)是最新的。
finally
來(lái)源 |??說(shuō)出你的愿望吧
來(lái)源 |??juejin.im/post/5d0bd358e51d45105e0212db
- End - 關(guān)注「開(kāi)源Linux」加星標(biāo),提升IT技能
