天天看點

ZooKeeper的Znode剖析類型節點的資料節點的屬性參考資料

在ZooKeeper中,節點也稱為znode。由于對于程式員來說,對zk的操作主要是對znode的操作,是以,有必要對znode進行深入的了解。

ZooKeeper采用了類似檔案系統的的資料模型,其節點構成了一個具有層級關系的樹狀結構。例如,圖1展示了zk節點的層級樹狀結構。

ZooKeeper的Znode剖析類型節點的資料節點的屬性參考資料

圖1:ZooKeeper的層級樹狀結構

圖1中,根節點 / 包含了兩個位元組點 /module1,/module2,而節點 /module1 又包含了三個位元組點 /module1/app1,/module1/app2,/module1/app3。在zk中,節點以絕對路徑表示,不存在相對路徑,且路徑最後不能以 / 結尾(根節點除外)。

類型

根據節點的存活時間,可以對節點劃分為持久節點和臨時節點。節點的類型在建立時就被确定下來,并且不能改變。

持久節點的存活時間不依賴于用戶端會話,隻有用戶端在顯式執行删除節點操作時,節點才消失。

臨時節點的存活時間依賴于用戶端會話,當會話結束,臨時節點将會被自動删除(當然也可以手動删除臨時節點)。利用臨時節點的這一特性,我們可以使用臨時節點來進行叢集管理,包括發現服務的上下線等。

ZooKeeper規定,臨時節點不能擁有子節點。

持久節點

使用指令create可以建立一個持久節點。

create /module1 module1

這樣,便建立了一個持久節點/module1,且其資料為”module1”。

臨時節點

使用create指令,并加上-e參數,可以建立一個臨時節點。

create -e /module1/app1 app1

這樣,便建立了一個臨時節點 /module1/app1,資料為”app1”。關閉會話,然後輸入指令:

get /module1/app1

可以看到有以下提示,說明臨時節點已經被删除。

Node does not exist: /module1/app1

順序節點

ZooKeeper中還提供了一種順序節點的節點類型。每次建立順序節點時,zk都會在路徑後面自動添加上10位的數字(計數器),例如 < path >0000000001,< path >0000000002,……這個計數器可以保證在同一個父節點下是唯一的。在zk内部使用了4個位元組的有符号整形來表示這個計數器,也就是說當計數器的大小超過2147483647時,将會發生溢出。

順序節點為節點的一種特性,也就是,持久節點和臨時節點都可以設定為順序節點。這樣一來,znode一共有4種類型:持久的、臨時的,持久順序的,臨時順序的。

使用指令create加上-s參數,可以建立順序節點,例如,

create -s /module1/app app

輸出:

Created /module1/app0000000001

便建立了一個持久順序節點 /module1/app0000000001。如果再執行此指令,則會生成節點 /module1/app0000000002。

如果在create -s再添加-e參數,則可以建立一個臨時順序節點。

節點的資料

在建立節點時,可以指定節點中存儲的資料。ZooKeeper保證讀和寫都是原子操作,且每次讀寫操作都是對資料的完整讀取或完整寫入,并不提供對資料進行部分讀取或者寫入的操作。

以下指令建立一個節點/module1/app2,且其存儲的資料為app2。

create /module1/app2 app2

ZooKeeper雖然提供了在節點存儲資料的功能,但它并不将自己定位為一個通用的資料庫,也就是說,你不應該在節點存儲過多的資料。Zk規定節點的資料大小不能超過1M,但實際上我們在znode的資料量應該盡可能小,因為資料過大會導緻zk的性能明顯下降。如果确實需要存儲大量的資料,一般解決方法是在另外的分布式資料庫(例如redis)中儲存這部分資料,然後在znode中我們隻保留這個資料庫中儲存位置的索引即可。

節點的屬性

每個znode都包含了一系列的屬性,通過指令get,我們可以獲得節點的屬性。

get /module1/app2

app2

cZxid = 0x20000000e

ctime = Thu Jun 30 20:41:55 HKT 2016

mZxid = 0x20000000e

mtime = Thu Jun 30 20:41:55 HKT 2016

pZxid = 0x20000000e

cversion = 0

dataVersion = 0

aclVersion = 0

ephemeralOwner = 0x0

dataLength = 4

numChildren = 0

版本号

對于每個znode來說,均存在三個版本号:

  • dataVersion

    資料版本号,每次對節點進行set操作,dataVersion的值都會增加1(即使設定的是相同的資料)。

  • cversion

    子節點的版本号。當znode的子節點有變化時,cversion 的值就會增加1。

  • aclVersion

    ACL的版本号,關于znode的ACL(Access Control List,通路控制),可以參考 參考資料1 有關ACL的描述。

以資料版本号來說明zk中版本号的作用。每一個znode都有一個資料版本号,它随着每次資料變化而自增。ZooKeeper提供的一些API例如setData和delete根據版本号有條件地執行。多個用戶端對同一個znode進行操作時,版本号的使用就會顯得尤為重要。例如,假設用戶端C1對znode /config寫入一些配置資訊,如果另一個用戶端C2同時更新了這個znode,此時C1的版本号已經過期,C1調用setData一定不會成功。這正是版本機制有效避免了資料更新時出現的先後順序問題。在這個例子中,C1在寫入資料時使用的版本号無法比對,使得操作失敗。圖2描述了這個情況。

ZooKeeper的Znode剖析類型節點的資料節點的屬性參考資料

圖2:使用版本号來阻止并行操作的不一緻性

事務ID

對于zk來說,每次的變化都會産生一個唯一的事務id,zxid(ZooKeeper Transaction Id)。通過zxid,可以确定更新操作的先後順序。例如,如果zxid1小于zxid2,說明zxid1操作先于zxid2發生。

需要指出的是,zxid對于整個zk都是唯一的,即使操作的是不同的znode。

  • cZxid

    Znode建立的事務id。

  • mZxid

    Znode被修改的事務id,即每次對znode的修改都會更新mZxid。

ZooKeeper的Znode剖析類型節點的資料節點的屬性參考資料

圖3:Zxid在用戶端重連中的作用

在叢集模式下,用戶端有多個伺服器可以連接配接,當嘗試連接配接到一個不同的伺服器時,這個伺服器的狀态要與最後連接配接的伺服器的狀态要保持一緻。Zk正是使用zxid來辨別這個狀态,圖3描述了用戶端在重連情況下zxid的作用。當用戶端因逾時與S1斷開連接配接後,用戶端開始嘗試連接配接S2,但S2延遲于用戶端所識别的狀态。然而,S3的狀态與用戶端所識别的狀态一緻,是以用戶端可以安全連接配接上S3。

時間戳

包括znode的建立時間和修改時間,建立時間是znode建立時的時間,建立後就不會改變;修改時間在每次更新znode時都會發生變化。

以下指令建立了一個 /module2 節點。

create /module2 module2

Created /module2

通過 get 指令,可以看到 /module2的 ctime和mtime均為Sat Jul 02 11:18:32 CST 2016。

get /module2

module2

cZxid = 0x2

ctime = Sat Jul 02 11:18:32 CST 2016

mZxid = 0x2

mtime = Sat Jul 02 11:18:32 CST 2016

pZxid = 0x2

cversion = 0

dataVersion = 0

aclVersion = 0

ephemeralOwner = 0x0

dataLength = 7

numChildren = 0

修改 /module2,可以看到 ctime 沒有發生變化,mtime已更新為最新的時間。

set /module2 module2_1

cZxid = 0x2

ctime = Sat Jul 02 11:18:32 CST 2016

mZxid = 0x3

mtime = Sat Jul 02 11:18:50 CST 2016

pZxid = 0x2

cversion = 0

dataVersion = 1

aclVersion = 0

ephemeralOwner = 0x0

dataLength = 9

numChildren = 0

參考資料

  1. http://zookeeper.apache.org/doc/trunk/zookeeperProgrammers.html#ch_zkDataModel
  2. http://java.globinch.com/enterprise-services/zookeeper/apache-zookeeper-explained-tutorial-cases-zookeeper-java-api-examples/#
  3. 《ZooKeeper分布式過程協同技術詳解》,Flavio Junqueira等著,謝超等譯