本篇文章結構:
總共包括10個系列
ZooKeeper系列之二:ZooKeeper數據模型、命名空間以及節點的概念
******************
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ZooKeeper 是一個爲分佈式應用所設計的分佈的、開源的協調服務。分佈式的應用可以建立在同步、配置管理、分組和命名等服務的更高級別的實現的基礎之上。 ZooKeeper 意欲設計一個易於編程的環境,它的文件系統使用我們所熟悉的目錄樹結構。 ZooKeeper 使用 Java 所編寫,但是支持 Java 和 C 兩種編程語言。
衆所周知,協調服務非常容易出錯,但是卻很難恢復正常,例如,協調服務很容易處於競態以至於出現死鎖。我們設計 ZooKeeper 的目的是爲了減輕分佈式應用程序所承擔的協調任務。
ZooKeeper系列之二:ZooKeeper數據模型、命名空間以及節點的概念
ZooKeeper數據模型和層次命名空間
提供的命名空間與標準的文件系統非常相似。一個名稱是由通過斜線分隔開的路徑名序列所組成的。ZooKeeper中的每一個節點是都通過路徑來識別。
下圖是Zookeeper中節點的數據模型,這種樹形結構的命名空間操作方便且易於理解。
圖:ZooKeeper層次命名空間
ZooKeeper中節點和臨時節點
ZooKeeper的節點是通過像樹一樣的結構來進行維護的,並且每一個節點通過路徑來標示以及訪問。除此之外,每一個節點還擁有自身的一些信息,包括:數據、數據長度、創建時間、修改時間等等。從這樣一類既含有數據,又作爲路徑表標示的節點的特點中,可以看出,ZooKeeper的節點既可以被看做是一個文件,又可以被看做是一個目錄,它同時具有二者的特點。爲了便於表達,今後我們將使用Znode來表示所討論的ZooKeeper節點。
具體地說,Znode維護着數據、ACL(access control list,訪問控制列表)、時間戳等交換版本號等數據結構,它通過對這些數據的管理來讓緩存生效並且令協調更新。每當Znode中的數據更新後它所維護的版本號將增加,這非常類似於數據庫中計數器時間戳的操作方式。
另外Znode還具有原子性操作的特點:命名空間中,每一個Znode的數據將被原子地讀寫。讀操作將讀取與Znode相關的所有數據,寫操作將替換掉所有的數據。除此之外,每一個節點都有一個訪問控制列表,這個訪問控制列表規定了用戶操作的權限。
ZooKeeper中同樣存在臨時節點。這些節點與session同時存在,當session生命週期結束,這些臨時節點也將被刪除。臨時節點在某些場合也發揮着非常重要的作用。
---------------------------
ZooKeeper的安裝模式分爲三種,分別爲:單機模式(stand-alone)、集羣模式和集羣僞分佈模式。ZooKeeper 單機模式的安裝相對比較簡單,如果第一次接觸ZooKeeper的話,建議安裝ZooKeeper單機模式或者集羣僞分佈模式。
1)單機模式
首先,從Apache官方網站下載一個ZooKeeper 的最近穩定版本。
http://hadoop.apache.org/zookeeper/releases.html
作爲國內用戶來說,選擇最近的的源文件服務器所在地,能夠節省不少的時間。
http://labs.renren.com/apache-mirror//hadoop/zookeeper/
ZooKeeper 要求 JAVA 的環境才能運行,並且需要 JAVA6 以上的版本,可以從 SUN 官網上下載,並對JAVA 環境變量進行設置。除此之外,爲了今後操作的方便,我們需要對 ZooKeeper 的環境變量進行配置,方法如下,在 /etc/profile 文件中加入如下的內容:
#Set ZooKeeper Enviroment
export ZOOKEEPER_HOME=/root/hadoop-0.20.2/zookeeper-3.3.1
export PATH=$PATH:$ZOOKEEPER_HOME/bin:$ZOOKEEPER_HOME/conf
ZooKeeper 服務器包含在單個 JAR 文件中,安裝此服務需要用戶創建一個配置文檔,並對其進行設置。我們在 ZooKeeper-*.*.* 目錄(我們以當前 ZooKeeper 的最新版 3.3.1 爲例,故此下面的“ ZooKeeper-*.*.* ”都將寫爲“ ZooKeeper-3.3.1” )的 conf 文件夾下創建一個 zoo.cfg 文件,它包含如下的內容:
tickTime=2000
dataDir=/var/zookeeper
clientPort=2181
在這個文件中,我們需要指定 dataDir 的值,它指向了一個目錄,這個目錄在開始的時候需要爲空。下面是每個參數的含義:
tickTime :基本事件單元,以毫秒爲單位。它用來指示心跳,最小的 session 過期時間爲兩倍的 tickTime. 。
dataDir :存儲內存中數據庫快照的位置,如果不設置參數,更新事務日誌將被存儲到默認位置。
clientPort :監聽客戶端連接的端口
使用單機模式時用戶需要注意:這種配置方式下沒有 ZooKeeper 副本,所以如果 ZooKeeper 服務器出現故障, ZooKeeper 服務將會停止。
以下代碼清單 A 是我們的根據自身情況所設置的 zookeeper 配置文檔: zoo.cfg
代碼清單 A : zoo.cfg
# The number of milliseconds of each tick
tickTime=2000
# the directory where the snapshot is stored.
dataDir=/root/hadoop-0.20.2/zookeeper-3.3.1/snapshot/data
# the port at which the clients will connect
clientPort=2181
2)集羣模式
爲了獲得可靠的 ZooKeeper 服務,用戶應該在一個集羣上部署 ZooKeeper 。只要集羣上大多數的ZooKeeper 服務啓動了,那麼總的 ZooKeeper 服務將是可用的。另外,最好使用奇數臺機器。 如果 zookeeper擁有 5 臺機器,那麼它就能處理 2 臺機器的故障了。
之後的操作和單機模式的安裝類似,我們同樣需要對 JAVA 環境進行設置,下載最新的 ZooKeeper 穩定版本並配置相應的環境變量。不同之處在於每臺機器上 conf/zoo.cfg 配置文件的參數設置,參考下面的配置:
tickTime=2000
dataDir=/var/zookeeper/
clientPort=2181
initLimit=5
syncLimit=2
server.1=zoo1:2888:3888
server.2=zoo2:2888:3888
server.3=zoo3:2888:3888
“ server.id=host:port:port. ”指示了不同的 ZooKeeper 服務器的自身標識,作爲集羣的一部分的機器應該知道 ensemble 中的其它機器。用戶可以從“ server.id=host:port:port. ”中讀取相關的信息。 在服務器的 data( dataDir 參數所指定的目錄)目錄下創建一個文件名爲 myid 的文件,這個文件中僅含有一行的內容,指定的是自身的 id 值。比如,服務器“ 1 ”應該在 myid 文件中寫入“ 1 ”。這個 id 值必須是 ensemble 中唯一的,且大小在 1 到 255 之間。這一行配置中,第一個端口( port )是從( follower )機器連接到主( leader )機器的端口,第二個端口是用來進行 leader 選舉的端口。在這個例子中,每臺機器使用三個端口,分別是: clientPort ,2181 ; port , 2888 ; port , 3888 。
我們在擁有三臺機器的 Hadoop 集羣上測試使用 ZooKeeper 服務,下面代碼清單 B 是我們根據自身情況所設置的 ZooKeeper 配置文檔:
代碼清單 B : zoo.cfg
# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
dataDir=/root/hadoop-0.20.2/zookeeper-3.3.1/snapshot/d1
# the port at which the clients will connect
clientPort=2181
server.1=IP1:2887:3887
server.2=IP2:2888:3888
server.3=IP3:2889:3889
清單中的 IP 分別對應的配置分佈式 ZooKeeper 的 IP 地址。當然,也可以通過機器名訪問 zookeeper ,但是需要在ubuntu 的 hosts 環境中進行設置。讀者可以查閱 Ubuntu 以及 Linux 的相關資料進行設置。
3)集羣僞分佈
簡單來說,集羣僞分佈模式就是在單機下模擬集羣的ZooKeeper服務。
那麼,如何對配置 ZooKeeper 的集羣僞分佈模式呢?其實很簡單,在 zookeeper 配置文檔中, clientPort參數用來設置客戶端連接 zookeeper 的端口。 server.1=IP1:2887:3887 中, IP1 指示的是組成 ZooKeeper 服務的機器 IP 地址, 2887 爲用來進行 leader 選舉的端口, 3887 爲組成 ZooKeeper 服務的機器之間通信的端口。集羣僞分佈模式我們使用每個配置文檔模擬一臺機器,也就是說,需要在單臺機器上運行多個 zookeeper 實例。但是,我們必須要保證各個配置文檔的 clientPort 不能衝突。
下面是我們所配置的集羣僞分佈模式,通過 zoo1.cfg , zoo2.cfg , zoo3.cfg 模擬了三臺機器的 ZooKeeper集羣。詳見代碼清單 C :
代碼清單C : zoo1.cfg :
# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
dataDir=/root/hadoop-0.20.2/zookeeper-3.3.1/d_1
# the port at which the clients will connect
clientPort=2181
server.1=localhost:2887:3887
server.2=localhost:2888:3888
server.3=localhost:2889:3889
zoo2.cfg :
# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
dataDir=/root/hadoop-0.20.2/zookeeper-3.3.1/d_2
# the port at which the clients will connect
clientPort=2182
#the location of the log file
dataLogDir=/root/hadoop-0.20.2/zookeeper-3.3.1/logs
server.1=localhost:2887:3887
server.2=localhost:2888:3888
server.3=localhost:2889:3889
zoo3.cfg :
# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
dataDir=/root/hadoop-0.20.2/zookeeper-3.3.1/d_2
# the port at which the clients will connect
clientPort=2183
#the location of the log file
dataLogDir=/root/hadoop-0.20.2/zookeeper-3.3.1/logs
server.1=localhost:2887:3887
server.2=localhost:2888:3888
server.3=localhost:2889:3889
從上述三個代碼清單中可以看到,除了 clientPort 不同之外, dataDir 也不同。另外,不要忘記在 dataDir 所對應的目錄中創建 myid 文件來指定對應的 zookeeper 服務器實例。
這裏ZooKeeper的安裝已經說完了,下一節我們來談一談對ZooKeeper的參數配置 的理解。
-------------------------------------------------
ZooKeeper 的功能特性通過 ZooKeeper 配置文件來進行控制管理( zoo.cfg 配置文件)。 ZooKeeper 這樣的設計其實是有它自身的原因的。通過前面對 ZooKeeper 的配置可以看出,對 ZooKeeper 集羣進行配置的時候,它的配置文檔是完全相同的(對於集羣僞分佈模式來說,只有很少的部分是不同的)。這樣的配置方使得在部署 ZooKeeper 服務的時候非常地方便。另外,如果服務器使用不同的配置文件,必須要確保不同配置文件中的服務器列表相匹配。
在設置 ZooKeeper 配置文檔的時候,某些參數是可選的,但是某些參數是必須的。這些必須的參數就構成了ZooKeeper 配置文檔的最低配置要求。
下面是在最低配置要求中必須配置的參數:
1 )最低配置
clientPort
監聽客戶端連接的端口;
dataDir
存儲內存中數據庫快照的位置;
注意 應該謹慎地選擇日誌存放的位置,使用專用的日誌存儲設備能夠大大地提高系統的性能,如果將日誌存儲在比較繁忙的存儲設備上,那麼將會在很大程度上影響系統的性能。
tickTime
基本事件單元,以毫秒爲單位。它用來控制心跳和超時,默認情況下最小的會話超時時間爲兩倍的 tickTime。
2 )高級配置
下面是高級配置要求中可選的配置參數,用戶可以使用下面的參數來更好地規定 ZooKeeper 的行爲:
dataLogDir
這個操作將管理機器把事務日誌寫入到“ dataLogDir ”所指定的目錄,而不是“ dataDir ”所指定的目錄。這將允許使用一個專用的日誌設備並且幫助我們避免日誌和快照之間的競爭。配置如下:
#the location of the log file
dataLogDir=/root/hadoop-0.20.2/zookeeper-3.3.1/log/data_log
這個操作將限制連接到 ZooKeeper 的客戶端的數量,限制併發連接的數量,它通過 IP 來區分不同的客戶端。此配置選項可以用來阻止某些類別的 Dos 攻擊。將它設置爲 0 或者忽略而不進行設置將會取消對併發連接的限制。
例如,此時我們將 maxClientCnxns 的值設置爲 1 ,如下所示:
#set maxClientCnxns
maxClientCnxns=1
啓動 ZooKeeper 之後,首先用一個客戶端連接到 ZooKeeper 服務器之上。然後,當第二個客戶端嘗試對ZooKeeper 進行連接,或者某些隱式的對客戶端的連接操作,將會觸發 ZooKeeper 的上述配置。系統會提示相關信息,如下圖 1 所示:
圖 1 : ZooKeeper maxClientCnxns 異常
minSessionTimeout 和 maxSessionTimeout
最小的會話超時時間以及最大的會話超時時間。其中,最小的會話超時時間默認情況下爲 2 倍的 tickTme 時間,最大的會話超時時間默認情況下爲 20 倍的會話超時時間。在啓動時,系統會顯示相應信息,見下圖 2 所示,默認會話超時時間:
圖2 :默認會話超時時間
從上圖中可以看書, minSessionTimeout 以及 maxSessionTimeout 的值均爲 -1 ,現在我們來設置系統的最小會話超時時間以及最大會話超時時間,如下所示:
#set minSessionTimeout
minSessionTimeout=1000
#set maxSessionTImeout
maxSessionTimeout=10000
在配置 minSessionTmeout 以及 maxSessionTimeout 的值的時候需要注意,如果將此值設置的太小的話,那麼會話很可能剛剛建立便由於超時而不得不退出。一般情況下,不能將此值設置的比 tickTime 的值還小。
3 )集羣配置
initLimit
此配置表示,允許 follower (相對於 leader 而言的“客戶端”)連接並同步到 leader 的初始化連接時間,它以 tickTime 的倍數來表示。當超過設置倍數的 tickTime 時間,則連接失敗。
syncLimit
此配置表示, leader 與 follower 之間發送消息,請求和應答時間長度。如果 follower 在設置的時間內不能與leader 進行通信,那麼此 follower 將被丟棄。
---------------------我們這裏所介紹的是對應 ZooKeeper系列之三:ZooKeeper的安裝 模式的運行。
1)單機模式
用戶可以通過下面的命令來啓動 ZooKeeper 服務:
zkServer.sh start
這個命令默認情況下執行 ZooKeeper 的 conf 文件夾下的 zoo.cfg 配置文件。當運行成功用戶會看到類似如下的提示界面:
root@ubuntu:~# zkServer.sh start
JMX enabled by default
Using config: /root/hadoop-0.20.2/zookeeper-3.3.1/bin/../conf/zoo.cfg
Starting zookeeper ...
STARTED
... ...
2011-01-19 10:04:42,300 - WARN [main:QuorumPeerMain@105] - Either no config or no quorum defined in config, running in standalone mode
... ...
2011-01-19 10:04:42,419 - INFO [main:ZooKeeperServer@660] - tickTime set to 2000
2011-01-19 10:04:42,419 - INFO [main:ZooKeeperServer@669] - minSessionTimeout set to -1
2011-01-19 10:04:42,419 - INFO [main:ZooKeeperServer@678] - maxSessionTimeout set to -1
2011-01-19 10:04:42,560 - INFO [main:NIOServerCnxn$Factory@143] - binding to port 0.0.0.0/0.0.0.0:2181
2011-01-19 10:04:42,806 - INFO [main:FileSnap@82] - Reading snapshot /root/hadoop-0.20.2/zookeeper-3.3.1/data/version-2/snapshot.200000036
2011-01-19 10:04:42,927 - INFO [main:FileSnap@82] - Reading snapshot /root/hadoop-0.20.2/zookeeper-3.3.1/data/version-2/snapshot.200000036
2011-01-19 10:04:42,950 - INFO [main:FileTxnSnapLog@208] - Snapshotting: 400000058
從上面可以看出,運行成功後,系統會列出 ZooKeeper 運行的相關環境配置信息。
2)集羣模式
集羣模式下需要用戶在每臺 ZooKeeper 機器上運行第一部分的命令,這裏不再贅述。
3)集羣僞分佈模式
在集羣僞分佈模式下,我們只有一臺機器,但是要運行三個 ZooKeeper 服務實例。此時,如果再使用上述命令式肯定行不通的。這裏,我們通過下面三條命能夠令來運行 ZooKeeper系列之三:ZooKeeper的安裝 中 我們配置的 ZooKeeper 服務。如下所示:
zkServer.sh start zoo1.cfg
zkServer.sh start zoo2.cfg
zkServer.sh start zoo3.cfg
在運行完第一條命令之後,讀者將會發現一些系統錯誤提示,如下圖 1 所示:
圖 1 :集羣僞分佈異常提示
產生如上圖所示的異常信息是由於 ZooKeeper 服務的每個實例都擁有全局的配置信息,它們在啓動的時候需要隨時地進行 Leader 選舉操作(此部分內容下面將會詳細講述)。此時第一個啓動的 Zookeeper 需要和另外兩個 ZooKeeper 實例進行通信。但是,另外兩個 ZooKeeper 實例還沒有啓動起來,因此將會產生上述所示的異常信息。
我們直接將其忽略即可,因爲當把圖示中的“ 2 號”和“ 3 號” ZooKeeper 實例啓動起來之後,相應的異常信息就回自然而然地消失。
----------------------------
ZooKeeper 支持某些特定的四字命令字母與其的交互。它們大多是查詢命令,用來獲取 ZooKeeper 服務的當前狀態及相關信息。用戶在客戶端可以通過 telnet 或 nc 向 ZooKeeper 提交相應的命令。 ZooKeeper 常用四字命令見下表 1 所示:
表 1 : ZooKeeper 四字命令
ZooKeeper 四字命令 |
功能描述 |
conf |
輸出相關服務配置的詳細信息。 |
cons |
列出所有連接到服務器的客戶端的完全的連接 / 會話的詳細信息。包括“接受 / 發送”的包數量、會話 id 、操作延遲、最後的操作執行等等信息。 |
dump |
列出未經處理的會話和臨時節點。 |
envi |
輸出關於服務環境的詳細信息(區別於 conf 命令)。 |
reqs |
列出未經處理的請求 |
ruok |
測試服務是否處於正確狀態。如果確實如此,那麼服務返回“imok ”,否則不做任何相應。 |
stat |
輸出關於性能和連接的客戶端的列表。 |
wchs |
列出服務器 watch 的詳細信息。 |
wchc |
通過 session 列出服務器 watch 的詳細信息,它的輸出是一個與watch 相關的會話的列表。 |
wchp |
通過路徑列出服務器 watch 的詳細信息。它輸出一個與 session相關的路徑。 |
下圖 1 是 ZooKeeper 四字命令的簡單用例:
圖 1 : ZooKeeper 四字命令用例
當啓動 ZooKeeper 服務成功之後,輸入下述命令,連接到 ZooKeeper 服務:
zkCli.sh –server 10.77.20.23:2181
連接成功後,系統會輸出 ZooKeeper 的相關環境以及配置信息,並在屏幕輸出“ Welcome to ZooKeeper”等信息。
輸入 help 之後,屏幕會輸出可用的 ZooKeeper 命令,如下圖 1 所示:
圖 1 : ZooKeeper 命令
ZooKeeper系列之八:ZooKeeper的簡單操作
1 )使用 ls 命令來查看當前 ZooKeeper 中所包含的內容:
[zk: 10.77.20.23:2181(CONNECTED) 1] ls /
[zookeeper]
2 )創建一個新的 znode ,使用 create /zk myData 。這個命令創建了一個新的 znode 節點“ zk ”以及與它關聯的字符串:
[zk: 10.77.20.23:2181(CONNECTED) 2] create /zk myData
Created /zk
3 )再次使用 ls 命令來查看現在 zookeeper 中所包含的內容:
[zk: 10.77.20.23:2181(CONNECTED) 3] ls /
[zk, zookeeper]
此時看到, zk 節點已經被創建。
4 )下面我們運行 get 命令來確認第二步中所創建的 znode 是否包含我們所創建的字符串:
[zk: 10.77.20.23:2181(CONNECTED) 4] get /zk
myData
Zxid = 0x40000000c
time = Tue Jan 18 18:48:39 CST 2011
Zxid = 0x40000000c
mtime = Tue Jan 18 18:48:39 CST 2011
pZxid = 0x40000000c
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 6
numChildren = 0
5 )下面我們通過 set 命令來對 zk 所關聯的字符串進行設置:
[zk: 10.77.20.23:2181(CONNECTED) 5] set /zk shenlan211314
cZxid = 0x40000000c
ctime = Tue Jan 18 18:48:39 CST 2011
mZxid = 0x40000000d
mtime = Tue Jan 18 18:52:11 CST 2011
pZxid = 0x40000000c
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 13
numChildren = 0
6 )下面我們將剛纔創建的 znode 刪除:
[zk: 10.77.20.23:2181(CONNECTED) 6] delete /zk
7 )最後再次使用 ls 命令查看 ZooKeeper 所包含的內容:
[zk: 10.77.20.23:2181(CONNECTED) 7] ls /
[zookeeper]
經過驗證, zk 節點已經被刪除。
ZooKeeper系列之九:ZooKeeper API簡介及編程
1)ZooKeeper API 簡介
ZooKeeper API 共包含 5 個包,分別爲: org.apache.zookeeper , org.apache.zookeeper.data ,org.apache.zookeeper.server , org.apache.zookeeper.server.quorum 和org.apache.zookeeper.server.upgrade 。其中 org.apache.zookeeper 包含 ZooKeeper 類,它我們編程時最常用的類文件。
這個類是 ZooKeeper 客戶端庫的主要類文件。如果要使用 ZooKeeper 服務,應用程序首先必須創建一個Zookeeper 實例,這時就需要使用此類。一旦客戶端和 ZooKeeper 服務建立起連接, ZooKeeper 系統將會分配給此連接回話一個 ID 值,並且客戶端將會週期地向服務器發送心跳來維持會話的連接。只要連接有效,客戶端就可以調用 ZooKeeper API 來做相應的處理。
它提供了表 1 所示幾類主要方法 , :
表 1 : ZooKeeper API 描述
功能 |
描述 |
create |
在本地目錄樹中創建一個節點 |
delete |
刪除一個節點 |
exists |
測試本地是否存在目標節點 |
get/set data |
從目標節點上讀取 / 寫數據 |
get/set ACL |
獲取 / 設置目標節點訪問控制列表信息 |
get children |
檢索一個子節點上的列表 |
sync |
等待要被傳送的數據 |
2)ZooKeeper API 的使用
這裏,筆者通過一個例子來簡單介紹,如何使用 ZooKeeper API 編寫自己的應用程序,見代碼清單 1 :
代碼清單 1 : ZooKeeper API 的使用
1. import java.io.IOException;
2.
3. import org.apache.zookeeper.CreateMode;
4. import org.apache.zookeeper.KeeperException;
5. import org.apache.zookeeper.Watcher;
6. import org.apache.zookeeper.ZooDefs.Ids;
7. import org.apache.zookeeper.ZooKeeper;
8.
9. public class demo {
10. // 會話超時時間,設置爲與系統默認時間一致
11. private static final int SESSION_TIMEOUT=30000;
12.
13. // 創建 ZooKeeper 實例
14. ZooKeeper zk;
15.
16. // 創建 Watcher 實例
17. Watcher wh=new Watcher(){
18. public void process(org.apache.zookeeper.WatchedEvent event)
19. {
20. System.out.println(event.toString());
21. }
22. };
23.
24. // 初始化 ZooKeeper 實例
25. private void createZKInstance() throws IOException
26. {
27. zk=new ZooKeeper("localhost:2181",demo.SESSION_TIMEOUT,this.wh);
28.
29. }
30.
31. private void ZKOperations() throws IOException,InterruptedException,KeeperException
32. {
33. System.out.println("/n1. 創建 ZooKeeper 節點 (znode : zoo2, 數據: myData2 ,權限:OPEN_ACL_UNSAFE ,節點類型: Persistent");
34. zk.create("/zoo2","myData2".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
35.
36. System.out.println("/n2. 查看是否創建成功: ");
37. System.out.println(new String(zk.getData("/zoo2",false,null)));
38.
39. System.out.println("/n3. 修改節點數據 ");
40. zk.setData("/zoo2", "shenlan211314".getBytes(), -1);
41.
42. System.out.println("/n4. 查看是否修改成功: ");
43. System.out.println(new String(zk.getData("/zoo2", false, null)));
44.
45. System.out.println("/n5. 刪除節點 ");
46. zk.delete("/zoo2", -1);
47.
48. System.out.println("/n6. 查看節點是否被刪除: ");
49. System.out.println(" 節點狀態: ["+zk.exists("/zoo2", false)+"]");
50. }
51.
52. private void ZKClose() throws InterruptedException
53. {
54. zk.close();
55. }
56.
57. public static void main(String[] args) throws IOException,InterruptedException,KeeperException {
58. demo dm=new demo();
59. dm.createZKInstance( );
60. dm.ZKOperations();
61. dm.ZKClose();
62. }
63.}
此類包含兩個主要的 ZooKeeper 函數,分別爲 createZKInstance ()和 ZKOperations ()。其中createZKInstance ()函數負責對 ZooKeeper 實例 zk 進行初始化。 ZooKeeper 類有兩個構造函數,我們這裏使用“ ZooKeeper ( String connectString, , int sessionTimeout, , Watcher watcher )”對其進行初始化。因此,我們需要提供初始化所需的,連接字符串信息,會話超時時間,以及一個 watcher 實例。 17 行到 23 行代碼,是程序所構造的一個 watcher 實例,它能夠輸出所發生的事件。
ZKOperations ()函數是我們所定義的對節點的一系列操作。它包括:創建 ZooKeeper 節點( 33 行到 34行代碼)、查看節點( 36 行到 37 行代碼)、修改節點數據( 39 行到 40 行代碼)、查看修改後節點數據( 42行到 43 行代碼)、刪除節點( 45 行到 46 行代碼)、查看節點是否存在( 48 行到 49 行代碼)。另外,需要注意的是:在創建節點的時候,需要提供節點的名稱、數據、權限以及節點類型。此外,使用 exists 函數時,如果節點不存在將返回一個 null 值。關於 ZooKeeper API 的更多詳細信息,讀者可以查看 ZooKeeper 的 API 文檔,如下所示:
--------------------------------------------------
ZooKeeper系列之十:ZooKeeper的一致性保證及Leader選舉
1)一致性保證
Zookeeper 是一種高性能、可擴展的服務。 Zookeeper 的讀寫速度非常快,並且讀的速度要比寫的速度更快。另外,在進行讀操作的時候, ZooKeeper 依然能夠爲舊的數據提供服務。這些都是由於 ZooKeepe 所提供的一致性保證,它具有如下特點:
順序一致性
客戶端的更新順序與它們被髮送的順序相一致。
原子性
更新操作要麼成功要麼失敗,沒有第三種結果。
單系統鏡像
無論客戶端連接到哪一個服務器,客戶端將看到相同的 ZooKeeper 視圖。
可靠性
一旦一個更新操作被應用,那麼在客戶端再次更新它之前,它的值將不會改變。。這個保證將會產生下面兩種結果:
1 .如果客戶端成功地獲得了正確的返回代碼,那麼說明更新已經成果。如果不能夠獲得返回代碼(由於通信錯誤、超時等等),那麼客戶端將不知道更新操作是否生效。
2 .當從故障恢復的時候,任何客戶端能夠看到的執行成功的更新操作將不會被回滾。
實時性
在特定的一段時間內,客戶端看到的系統需要被保證是實時的(在十幾秒的時間裏)。在此時間段內,任何系統的改變將被客戶端看到,或者被客戶端偵測到。
給予這些一致性保證, ZooKeeper 更高級功能的設計與實現將會變得非常容易,例如: leader 選舉、隊列以及可撤銷鎖等機制的實現。
2)Leader選舉
ZooKeeper 需要在所有的服務(可以理解爲服務器)中選舉出一個 Leader ,然後讓這個 Leader 來負責管理集羣。此時,集羣中的其它服務器則成爲此 Leader 的 Follower 。並且,當 Leader 故障的時候,需要ZooKeeper 能夠快速地在 Follower 中選舉出下一個 Leader 。這就是 ZooKeeper 的 Leader 機制,下面我們將簡單介紹在 ZooKeeper 中, Leader 選舉( Leader Election )是如何實現的。
此操作實現的核心思想是:首先創建一個 EPHEMERAL 目錄節點,例如“ /election ”。然後。每一個ZooKeeper 服務器在此目錄下創建一個 SEQUENCE| EPHEMERAL 類型的節點,例如“ /election/n_ ”。在SEQUENCE 標誌下, ZooKeeper 將自動地爲每一個 ZooKeeper 服務器分配一個比前一個分配的序號要大的序號。此時創建節點的 ZooKeeper 服務器中擁有最小序號編號的服務器將成爲 Leader 。
在實際的操作中,還需要保障:當 Leader 服務器發生故障的時候,系統能夠快速地選出下一個 ZooKeeper服務器作爲 Leader 。一個簡單的解決方案是,讓所有的 follower 監視 leader 所對應的節點。當 Leader 發生故障時, Leader 所對應的臨時節點將會自動地被刪除,此操作將會觸發所有監視 Leader 的服務器的 watch 。這樣這些服務器將會收到 Leader 故障的消息,並進而進行下一次的 Leader 選舉操作。但是,這種操作將會導致“從衆效應”的發生,尤其當集羣中服務器衆多並且帶寬延遲比較大的時候,此種情況更爲明顯。
在 Zookeeper 中,爲了避免從衆效應的發生,它是這樣來實現的:每一個 follower 對 follower 集羣中對應的比自己節點序號小一號的節點(也就是所有序號比自己小的節點中的序號最大的節點)設置一個 watch 。只有當follower 所設置的 watch 被觸發的時候,它才進行 Leader 選舉操作,一般情況下它將成爲集羣中的下一個Leader 。很明顯,此 Leader 選舉操作的速度是很快的。因爲,每一次 Leader 選舉幾乎只涉及單個 follower 的操作。