面試官問(wèn):ZooKeeper 有幾種節(jié)點(diǎn)類(lèi)型?別回答 4 種啦
本文轉(zhuǎn)載自微信公眾號(hào)「HelloGitHub」,作者HelloGitHub。轉(zhuǎn)載本文請(qǐng)聯(lián)系HelloGitHub公眾號(hào)。
一、關(guān)于 ZK 的節(jié)點(diǎn)類(lèi)型
大家如果刷過(guò) ZK 相關(guān)面試題的話(huà),就一定會(huì)刷到過(guò) “ZK 有幾種節(jié)點(diǎn)類(lèi)型?”,大家通常背書(shū)的答案的話(huà)是:4 種!但其實(shí) ZK (3.6.2)服務(wù)端支持 7 種節(jié)點(diǎn)類(lèi)型,分別是:
- 持久
- 持久順序
- 臨時(shí)
- 臨時(shí)順序
- 容器
- 持久 TTL
- 持久順序 TTL
這 7 種類(lèi)型之前的文章中也有提到過(guò),但是并沒(méi)有展開(kāi)講。這次更新的單篇想要把這 7 種類(lèi)型的節(jié)點(diǎn),認(rèn)認(rèn)真真的講一遍!Let's GO
二、簡(jiǎn)單介紹
2.1 持久、臨時(shí)
持久不用我多說(shuō),是用的最多的一種類(lèi)型,也是默認(rèn)的節(jié)點(diǎn)類(lèi)型,臨時(shí)節(jié)點(diǎn)相較于持久節(jié)點(diǎn)來(lái)說(shuō),就是它會(huì)隨著客戶(hù)端會(huì)話(huà)結(jié)束而被刪除,通??梢杂迷谝恍┨囟ǖ膱?chǎng)景,例如分布式鎖釋放,健康檢查等。
2.2 持久順序、臨時(shí)順序
這兩種我放在一起介紹,因?yàn)樗麄兿鄬?duì)于上面兩種的特性就是 ZK 會(huì)自動(dòng)在這兩種節(jié)點(diǎn)之后增加一個(gè)數(shù)字的后綴,而路徑 + 數(shù)字后綴是能保證唯一的,這數(shù)字后綴的應(yīng)用場(chǎng)景可以實(shí)現(xiàn)諸如分布式隊(duì)列,分布式公平鎖等。
2.3 容器
容器節(jié)點(diǎn)是 3.5 以后新增的節(jié)點(diǎn)類(lèi)型,只要在調(diào)用 create 方法時(shí),指定 CreateMode 為 CONTAINER 即可創(chuàng)建容器的節(jié)點(diǎn)類(lèi)型,容器節(jié)點(diǎn)的表現(xiàn)形式和持久節(jié)點(diǎn)是一樣的,但是區(qū)別是 ZK 服務(wù)端啟動(dòng)后,會(huì)有一個(gè)單獨(dú)的線(xiàn)程去掃描,所有的容器節(jié)點(diǎn),當(dāng)發(fā)現(xiàn)容器節(jié)點(diǎn)的子節(jié)點(diǎn)數(shù)量為 0 時(shí),會(huì)自動(dòng)刪除該節(jié)點(diǎn),除此之外和持久節(jié)點(diǎn)沒(méi)有區(qū)別,官方注釋給出的使用場(chǎng)景是 Container nodes are special purpose nodes useful for recipes such as leader, lock, etc. 說(shuō)可以用在 leader 或者鎖的場(chǎng)景中。
2.4 持久 TTL、持久順序 TTL
關(guān)于持久和順序這兩個(gè)關(guān)鍵字,不用我再解釋了,這兩種類(lèi)型的節(jié)點(diǎn)重點(diǎn)是后面的 TTL,TTL 是 time to live 的縮寫(xiě),指帶有存活時(shí)間,簡(jiǎn)單來(lái)說(shuō)就是當(dāng)該節(jié)點(diǎn)下面沒(méi)有子節(jié)點(diǎn)的話(huà),超過(guò)了 TTL 指定時(shí)間后就會(huì)被自動(dòng)刪除,特性跟上面的容器節(jié)點(diǎn)很像,只是容器節(jié)點(diǎn)沒(méi)有超時(shí)時(shí)間而已,但是 TTL 啟用是需要額外的配置(這個(gè)之前也有提過(guò))配置是 zookeeper.extendedTypesEnabled 需要配置成 true,否則的話(huà)創(chuàng)建 TTL 時(shí)會(huì)收到 Unimplemented 的報(bào)錯(cuò)
三、原理介紹
單純的持久和臨時(shí)節(jié)點(diǎn)我就不介紹了,之前的系列文章有講
3.1 順序關(guān)鍵字
客戶(hù)端創(chuàng)建一個(gè)順序節(jié)點(diǎn)的時(shí)候,服務(wù)端得知當(dāng)前節(jié)點(diǎn)是順序節(jié)點(diǎn)的時(shí)候會(huì)自動(dòng)給路徑加上后綴,后綴就是父節(jié)點(diǎn)的 cversion,代表創(chuàng)建子節(jié)點(diǎn)的個(gè)數(shù)
- if (createMode.isSequential()) {
- path = path + String.format(Locale.ENGLISH, "%010d", parentCVersion);
- }
就是這么簡(jiǎn)單~
3.2 容器、TTL 關(guān)鍵字
這兩種其實(shí)可以放在一起講,服務(wù)端在啟動(dòng)的時(shí)候會(huì)額外啟動(dòng)一個(gè)定時(shí)任務(wù)線(xiàn)程,會(huì)定期的掃描所有的容器和 TTL 的節(jié)點(diǎn),逐一判斷子節(jié)點(diǎn)的數(shù)量以及一些相關(guān)配置,來(lái)決定是否刪除,首先整個(gè)邏輯是在 ContainerManager 中,定時(shí)任務(wù)是由 TimeTask 實(shí)現(xiàn)的,相關(guān)的配置有
配置項(xiàng) | 默認(rèn)值 | 說(shuō)明 |
---|---|---|
znode.container.checkIntervalMs | 60000(毫秒) | 定時(shí)任務(wù)檢查的間隔 |
znode.container.maxPerMinute | 10000 | 和上面的參數(shù)聯(lián)合成為最小的檢查間隔,每個(gè)節(jié)點(diǎn)間隔必須差 (60000 / 10000)毫秒(默認(rèn) 6 毫秒)以上 |
znode.container.maxNeverUsedIntervalMs | 0 | 如果配置不為 0 的話(huà),當(dāng)容器和 TTL 節(jié)點(diǎn)最后一次更新的時(shí)間和當(dāng)前時(shí)間戳的差超過(guò)這個(gè)值的話(huà),也會(huì)被刪除 |
四、小結(jié)
- 持久關(guān)鍵字:客戶(hù)端不主動(dòng)刪除的話(huà),節(jié)點(diǎn)數(shù)據(jù)會(huì)一直存在
- 臨時(shí)關(guān)鍵字:客戶(hù)端連接斷開(kāi)后,節(jié)點(diǎn)數(shù)據(jù)會(huì)被一起刪除
- 順序關(guān)鍵字:服務(wù)端會(huì)自動(dòng)為該節(jié)點(diǎn)加數(shù)字后綴
- 容器:服務(wù)端會(huì)定期掃描這些節(jié)點(diǎn),當(dāng)該節(jié)點(diǎn)下面沒(méi)有子節(jié)點(diǎn)時(shí)(或其他條件時(shí))服務(wù)端會(huì)自動(dòng)刪除節(jié)點(diǎn)
- TTL:需要額外配置才能啟用,基本和容器相同,當(dāng)超過(guò) TTL 時(shí)間節(jié)點(diǎn)下面都沒(méi)有再創(chuàng)建子節(jié)點(diǎn)時(shí)會(huì)被刪除,但是當(dāng)創(chuàng)建子節(jié)點(diǎn)會(huì)重置該超時(shí)時(shí)間