目錄
1、zookeeper自帶的zkCli客戶端命令行
當進入zkCli的命令行,可以輸入help顯示出所有操作的命令,如下表:
命令基本語法 |
功能描述 |
help |
顯示所有操作命令 |
ls path [watch] |
使用 ls 命令來查看當前znode中所包含的內容 |
ls2 path [watch] |
查看當前節點數據並能看到更新次數等數據 |
create |
普通創建 -s 含有序列 -e 臨時(重啓或者超時消失) |
get path [watch] |
獲得節點的值 |
set |
設置節點的具體值 |
stat |
查看節點狀態 |
delete |
刪除節點 |
rmr |
遞歸刪除節點 |
示例:
查看所有節點: ls / ls2 / (顯示的更詳細)
創建普通節點: create path data
如:create /xiyou "sunwukong"
獲取節點值:get path
如:get /xiyou
創建臨時節點:create -e /sanguo "xiaoqiao"
創建的這個臨時節點,在客戶端退出時就會被刪除
創建帶序號節點:create -s /xiyou/sunhouzi "sunwukong"
修改節點的值: set path data
如:set /xiyou "wujing"
節點的值變化監聽:get /xiyou watch(說明:這種監聽只會生效一次)
驗證:可以在A客戶端中執行監聽,在B客戶端修改/xiyou的值,此時A客戶端會出現如下提示
WatchedEvent state:SyncConnected type:NodeDataChanged path:/sanguo/simayi
說明監聽節點的值已被修改。
節點路徑的變化監聽:ls /sanguo watch(說明:這種監聽只會生效一次)
驗證:在A客戶端執行監聽,通過B客戶端在/sanguo目錄下新增一個節點,在hadoop102上觀察效果
在A客戶端會出現如下提示:
WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/sanguo
刪除節點(子節點):delete /xiyou/bajie
遞歸刪除節點: rmr /xiyou
查看節點狀態: stat /sanguo
2、使用zookeeper原生API
(1)環境搭建
使用maven工程,在pom.xml中引入原生的Zookeeper API。
<!--zookeeper原生API -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.10</version>
</dependency>
<!-- 單元測試-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
version>4.12</version>
<scope>compile</scope>
/dependency>
(2)代碼示例
a、創建客戶端
new Zookeeper(zookeeper地址, session超時時間, 監聽事件)
原生的zookeeper存在缺陷:註冊事件只生效一次,因此需要人爲在process回調中再次註冊監聽事件。
@Before
public void initZk() throws Exception {
zooKeeper = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
public void process(WatchedEvent watchedEvent) {
//監聽發生後觸發的事件
System.out.println(watchedEvent.getType() + "---" + watchedEvent.getPath());
//再次註冊事件進行監聽
try {
zooKeeper.exists("/liuzhoujian", true);
zooKeeper.getChildren("/", true);
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
b、創建節點
@Test
public void createNode() throws Exception {
//第一個參數:節點路徑
//第二個參數:存儲的數據
//第三個參數:訪問的權限
//第四個參數:節點的類型
String node = zooKeeper.create("/liuzhoujian", "movie.txt".getBytes(),
ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println(node);
}
c、刪除節點
當不需要某個節點,或者某個節點的信息已經失效時,使用delete方法可以刪除節點,刪除時需要指定節點的版本號,如果設置爲-1,則匹配所有版本,zookeeper會比較刪除的節點版本是否和服務器上的版本一致,如果不一致則拋出異常。
zookeeper.delete("/liuzhoujian", -1);
d、設置和獲取節點內容
setData設置數據,getData獲取數據,其中每個節點最多存入1M數據。
getData() 第一個參數:節點路徑 第二個參數:是否使用監聽,false表示不使用 第三個參數:stat 表示節點的狀態,將會返回該節點當前的狀態信息
//設置版本號爲-1,如果匹配不到相應節點會拋出異常
zooKeeper.setData("/liuzhoujian", "hello".getBytes(), -1);
Stat stat = new Stat();
byte[] data = zooKeeper.getData("/liuzhoujian", false, stat);
e、添加子節點
String parent= zooKeeper.create("/liuzhoujian", "parent".getBytes(),
ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
String child = zooKeeper.create("/liuzhoujian/child", "child".getBytes(),
ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
f、判斷節點是否存在
@Test
public void isExist() throws Exception {
Stat stat = zooKeeper.exists("/liuzhoujian", true); //watch爲true表示開啓監聽,默認只監聽一次,需在process回調中再次配置
System.out.println(stat == null ? "nost exist" : "exist");
Thread.sleep(Long.MAX_VALUE); //爲了阻塞,能觀察到監聽器的處理效果
};
g、獲取根目錄下所有節點
@Test
public void getNode() throws Exception {
List<String> children = zooKeeper.getChildren("/", true);
for(String node : children) {
System.out.println(node);
}
Thread.sleep(Long.MAX_VALUE);
}
g、watcher的實現
當節點狀態發生變化時,通過watcher繪製,可以讓客戶端得到通知,watcher需要實現org.apache.ZooKeeper.Watcher接口。節點的狀態變化主要分爲:
節點狀態變化 | 解釋 |
EventType.NodeDeleted | 刪除節點 |
EventType.NodeChildrenChanged | 修改節點的子節點 |
EventType.NodeCreated | 創建節點 |
EventType.NodeDataChanged | 修改節點數據 |
public class ZKWatcher implementes Watcher {
@Override
public void process(WatchedEvent event) {
//監聽發生後觸發的事件
if(event.getType() == Event.EventType.NodeDeleted) {
System.out.println("node deleted");
} else if(event.getType() == Event.EventType.NodeChildrenChanged) {
System.out.println("nodeChildrenChanged");
} else if(event.getType() == Event.EventType.NodeCreated) {
System.out.println("node created");
} else if(event.getType() == Event.EventType.NodeDataChanged) {
System.out.println("node data changed");
}
}
}
需要注意的是:Zookeeper的watcher是一次性的,每次在處理完狀態變化事件後,需要重新註冊watcher。這個特性也使得在處理時間和重新加上watcher這段時間發生的節點狀態變化無法被感知。
文章參考:《大型分佈式網站架構設計與實踐》