本章主要介紹zookeeper如何使用,其實通過zkCli.cmd我們是可以執行一些操作的:
聲明:參考及轉自《http://www.blogjava.net/BucketLi/archive/2010/12/21/341268.html》
- 通過zkCli.cmd來操作zookeeper:
進入D:\Work\zookeeper\zookeeper-3.4.8\bin的路徑下,在cmd下輸入命令:zkCli.sh –server 127.0.0.1:2182,之后通過help命令可以查看到zkClient工具提供了以下操作命令。
[zk: 127.0.0.1:2181(CONNECTED) 10] help ZooKeeper -server host:port cmd args stat path [watch] set path data [version] ls path [watch] delquota [-n|-b] path ls2 path [watch] setAcl path acl setquota -n|-b val path history redo cmdno printwatches on|off delete path [version] sync path listquota path rmr path get path [watch] create [-s] [-e] path data acl addauth scheme auth quit getAcl path close connect host:port [zk: 127.0.0.1:2181(CONNECTED) 11]
ls(查看當前節點數據),
ls2(查看當前節點數據並能看到更新次數等數據) ,
create(創建一個節點) ,
get(得到一個節點,包含數據和更新次數等數據),
set(修改節點)
delete(刪除一個節點)
通過上述命令實踐,發現zookeeper使用了一個類似文件系統的樹結構,數據可以掛在某個節點上,可以對這個節點進行刪改。另外我們還發現,當改動一個節點的時候,集群中活着的機器都會更新到一致的數據(這里都是通過zkCli.cmd連接到任意一個zkServer時,通過查看數據時發現)。
- Zookeeper的數據存儲結構
通過ls /{目錄}命令查看那zk的數據存儲結構,可以發現其數據結構有些像操作系統的文件結構,結構如下圖所示:
(1) 每個節點在zookeeper中叫做znode,並且其有一個唯一的路徑標識,如/SERVER2節點的標識就為/APP3/SERVER2
(2) Znode可以有子znode,並且znode里可以存數據,但是EPHEMERAL類型的節點不能有子節點
(3) Znode中的數據可以有多個版本,比如某一個路徑下存有多個數據版本,那么查詢這個路徑下的數據就需要帶上版本。
(4) znode 可以是臨時節點,一旦創建這個 znode 的客戶端與服務器失去聯系,這個 znode 也將自動刪除,Zookeeper 的客戶端和服務器通信采用長連接方式,每個客戶端和 服務器通過心跳來保持連接,這個連接狀態稱為 session,如果 znode 是臨時節點,這個 session 失效,znode 也就刪除了
(5) znode 的目錄名可以自動編號,如 App1 已經存在,再創建的話,將會自動命名為 App2
(6) znode 可以被監控,包括這個目錄節點中存儲的數據的修改,子節點目錄的變化等,一旦變化可以通知設置監控的客戶端,這個功能是zookeeper對於應用最重要的特性,通過這個特性可以實現的功能包括配置的集中管理,集群管理,分布式鎖等等。
- 通過java來實現zkCiient連接zkServer:
1)使用eclipse做為開發測試的ide,通過maven構建一個Java project
maven引入zookeeper的jar:
<dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.8</version> </dependency>
2)編寫測試代碼:
1 package com.dx.zktest; 2 3 import java.util.List; 4 import java.io.IOException; 5 6 import org.apache.zookeeper.CreateMode; 7 import org.apache.zookeeper.KeeperException; 8 import org.apache.zookeeper.WatchedEvent; 9 import org.apache.zookeeper.Watcher; 10 import org.apache.zookeeper.ZooDefs.Ids; 11 import org.apache.zookeeper.ZooKeeper; 12 13 /** 14 * Hello world! 15 * 16 */ 17 public class ZkClient { 18 public static void main(String[] args) throws IOException, KeeperException, InterruptedException { 19 // 創建一個Zookeeper實例,第一個參數為目標服務器地址和端口,第二個參數為Session超時時間,第三個為節點變化時的回調方法 20 ZooKeeper zk = new ZooKeeper("127.0.0.1:2181", 500000, new Watcher() { 21 // 監控所有被觸發的事件 22 public void process(WatchedEvent event) { 23 // dosomething 24 System.out.println("watcher event fire..."); 25 } 26 }); 27 28 // 創建一個節點root,數據是mydata,不進行ACL權限控制,節點為永久性的(即客戶端shutdown了也不會消失) 29 zk.create("/root", "mydata".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); 30 31 // 在root下面創建一個childone znode,數據為childone,不進行ACL權限控制,節點為永久性的 32 zk.create("/root/childone", "childone".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); 33 34 // 取得/root節點下的子節點名稱,返回List<String> 35 List<String> rootItems = zk.getChildren("/root", true); 36 System.out.println("print /root..."); 37 for (String item : rootItems) { 38 System.out.println(item); 39 } 40 41 // 取得/root/childone節點下的數據,返回byte[] 42 byte[] bytes = zk.getData("/root/childone", true, null); 43 System.out.println(new String(bytes)); 44 45 // 修改節點/root/childone下的數據,第三個參數為版本,如果是-1,那會無視被修改的數據版本,直接改掉 46 zk.setData("/root/childone", "childonemodify".getBytes(), -1); 47 48 // 刪除/root/childone這個節點,第二個參數為版本,-1的話直接刪除,無視版本 49 zk.delete("/root/childone", -1); 50 51 // 關閉session 52 zk.close(); 53 } 54 }
使用zkCli.cmd監控服務器節點變化情況: