Apache zookeeper 資料模型
根據上一片的講解,我們配置了單機和分散式叢集,下面我們來了解一下 ZooKeeper資料模型:
根據ZooKeeper wiki的定義,ZooKeeper允許分散式程序通過資料暫存器的共享分層名稱空間相互協調。名稱空間看起來非常類似於Unix檔案系統。 資料暫存器在ZooKeeper命名中被稱為znode。 可以在下面的圖片中看到znodes的例子:
在這裡,可以看到znode是一個標準的檔案系統,層次結構很像一棵樹。 需要注意的一些要點如下:
- 根節點有一個名為/zoo的子節點,它又有三個znode。
- ZooKeeper樹中的每個znode都由一個路徑標識,路徑元素由『/』分隔。
- 這些節點被稱為資料暫存器,因為它們可以儲存資料。 因此,一個znode可以有子節點以及與之相關的資料。 這與檔案系統可以把檔案作為路徑很類似。
znode中的資料通常以位元組格式儲存,每個znode中的最大資料大小不超過1 MB。 ZooKeeper是為協調而設計的,幾乎所有形式的協調資料都比較小, 因此,對資料大小的限制是強制的。 建議實際的資料大小也要小於這個限制。
斜槓分隔的znode路徑是規範的,必須是絕對路徑。 相對路徑和引用不被ZooKeeper識別。 znode名稱可以由Unicode字元組成並且znode可以具有任何名稱。 這個例外是ZooKeeper這個詞是保留的。 最重要的是,使用“.” 作為一個路徑元件是非法的。
與檔案系統中的檔案一樣,znode維護一個stat結構,其中包含資料更改的版本號以及隨更改相關的時間戳而更改的訪問控制列表。 只要znode的資料發生變化,版本號就會增加。 ZooKeeper使用版本號以及相關的時間戳來驗證它的核心內快取。 znode版本號還允許客戶端通過ZooKeeper API更新或刪除特定的znode。 如果指定的版本號與znode的當前版本不匹配,則操作失敗。 但是,執行znode更新或刪除操作時,可以通過指定0作為版本號來覆蓋。
(1) znode的型別
ZooKeeper有兩種型別的znode:persistent和ephemeral。 可能已經聽說過第三種類型,稱為sequential的znode,這是另一種型別的限定符。 persistent和ephemeral的znode也可以是sequential的znode。 請注意,znode的型別是在建立時設定的。
(2) persistent型別的znode
顧名思義,persistent的znode在ZooKeeper的名稱空間中有一個生命週期,直到它們被明確的刪除。 一個znode可以通過呼叫delete API呼叫來刪除。 沒有必要只有建立持久化znode的客戶端才能刪除它。 請注意,任何ZooKeeper服務的授權客戶端都可以刪除一個znode。
現在使用ZooKeeper Java shell建立一個持久化的znode:
[zk: localhost(CONNECTED) 1] create /[PacktPub] "ApacheZooKeeper"
Created /[PacktPub]
[zk: localhost(CONNECTED) 2] get /[PacktPub]
"ApacheZooKeeper"
persistent的znodes對於儲存需要高度可用且可由分散式應用程式的所有元件訪問的資料時非常有用。 例如,應用程式可以將配置資料儲存在持久的znode中。 即使建立者客戶端死亡,資料以及znode也會存在。
(3) ephemeral型別的znode
相比之下,當建立客戶端的會話結束時,ZooKeeper服務會刪除一個ephemeral的znode。 客戶端會話的結束可能由於客戶端崩潰或連線的明確終止而發生斷開連線。 儘管臨時節點與客戶端會話繫結,但它們對所有客戶端均可見,具體取決於配置的訪問控制列表(ACL)策略。
建立者客戶端或任何其他授權客戶端也可以通過使用刪除API呼叫來顯式刪除ephemeral 的znode。 一旦其建立者客戶端與ZooKeeper服務的會話結束,ephemeral 的znode就不復存在。 因此,在當前版本的ZooKeeper中,短暫的znodes不允許有子節點。
要使用ZooKeeper Java Shell建立一個ephemeral的znode,必須在create命令中指定-e標誌,可以使用以下命令完成:
[zk: localhost(CONNECTED) 1] create -e /[PacktPub] "ApacheZooKeeper"
Created /[PacktPub]
現在,由於一個ephemeral的znode不允許有子節點,如果我們試圖建立一個剛剛建立的子節點znode時,會被丟擲一個錯誤,如下所示:
[zk: localhost(CONNECTED) 2] create -e /[PacktPub]/EphemeralChild "ChildOfEphemeralZnode"
Ephemerals cannot have children: /[PacktPub]/EphemeralChild
ephemeral的節點的用途可用於構建分散式應用程式,其中元件需要知道其他元件或資源的狀態。 例如,分散式組成員資格服務可以通過使用ephemera 的znode來實現。 當建立者客戶端會話結束時,ephemeral節點被刪除的屬性可用作加入或離開分散式叢集的節點的模擬。 使用會員服務,任何節點都能夠在任何特定的時間發現組的成員。
(4)sequential型別的znode
一個sequential的znode在ZooKeeper建立它的時候,分配一個序列號作為其名字的一部分。 一個單調遞增的計數器(由父znode維護)的值被附加到znode的名稱上。
計數器是一個有符號整數型別(4個位元組),用來儲存序號的。 它一共10位的格式,前面填充0。 例如,/path/to/znode-0000000001。 這個命名約定對分配給它們的值對sequential的znode進行排序很有用。
Note
sequential的節點可以用於實現分散式全域性佇列,因為順序號可以強制一個全域性順序。
它們也可以用來為分散式應用程式設計一個鎖定服務。
由於persistent和ephemeral的znode都可以是sequential型別的znode,因此總共有四種znode模式:
- persistent
- ephemeral
- persistent_sequential
- ephemeral_sequential
使用ZooKeeper Java shell建立一個sequential的znode,我們必須使用create命令的-s標誌:
[zk: localhost(CONNECTED) 1] create -s /[PacktPub] "PersistentSequentialZnode"
Created /[PacktPub]0000000001
[zk: localhost(CONNECTED) 3] create -s -e /[PacktPub] "EphemeralSequentialZnode"
Created /[PacktPub]0000000008