1. 數據存儲
事務日誌
快照日誌
運行時日誌 bin/zookeeper.out
2 基於 Java API 初探 zookeeper 的使用
2.1 zookeeper 增刪改查
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
/**
* @author: xiepanpan
* @Date: 2020/5/30
* @Description: zookeeper 連接
*/
public class ConnectionDemo {
public static void main(String[] args) throws Exception {
try {
final CountDownLatch countDownLatch = new CountDownLatch(1);
ZooKeeper zooKeeper =
new ZooKeeper("192.168.217.130:2181,192.168.217.130:2183,192.168.217.130:2183", 4000, new Watcher() {
public void process(WatchedEvent watchedEvent) {
//如果收到了服務端的響應事件,連接成功
if (Event.KeeperState.SyncConnected==watchedEvent.getState()) {
countDownLatch.countDown();
}
}
});
countDownLatch.await();
//CONNECTED
System.out.println(zooKeeper.getState());
//創建節點 第三個參數是權限 OPEN_ACL_UNSAFE 所有人都可以訪問 第四個參數 節點類型 持久節點
zooKeeper.create("/zk-persistent-xpp","0".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
Thread.sleep(1000);
//得到節點
Stat stat = new Stat();
byte[] bytes = zooKeeper.getData("/zk-persistent-xpp", null, stat);
System.out.println(new String(bytes));
//修改節點
zooKeeper.setData("/zk-persistent-xpp","1".getBytes(),stat.getVersion());
byte[] data = zooKeeper.getData("/zk-persistent-xpp", null, stat);
System.out.println(new String(data));
//刪除節點 使用樂觀鎖 比較版本號
zooKeeper.delete("/zk-persistent-xpp",stat.getVersion());
zooKeeper.close();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
2.2 事件機制
Watcher 監聽機制是 Zookeeper 中非常重要的特性,我們基於 zookeeper 上創建的節點,可以對這些節點綁定監聽
事件,比如可以監聽節點數據變更、節點刪除、子節點狀態變更等事件,通過這個事件機制,可以基於 zookeeper
實現分佈式鎖、集羣管理等功能
watcher 特性:當數據發生變化的時候, zookeeper 會產生一個 watcher 事件,並且會發送到客戶端。但是客戶端
只會收到一次通知。如果後續這個節點再次發生變化,那麼之前設置 watcher 的客戶端不會再次收到消息。(watcher 是一次性的操作)。 可以通過循環監聽去達到永久監聽效果
2.3 如何註冊事件機制
通過這三個操作來綁定事件 :getData、Exists、getChildren
2.4 如何觸發事件?
凡是事務類型的操作,都會觸發監聽事件。
create /delete /setData
2.5 watcher 事件類型
None (-1), 客戶端鏈接狀態發生變化的時候,會收到 none 的事件
NodeCreated (1), 創建節點的事件。 比如 zk-persis-mic
NodeDeleted (2), 刪除節點的事件
NodeDataChanged (3), 節點數據發生變更
NodeChildrenChanged (4); 子節點被創建、被刪除、會發生事件觸發
2.6 操作對應的water事件類型
zk-persis-mic ( 監聽事件) | zk-persis-mic/child (子節點監聽事件) | |
---|---|---|
create(/ zk-persis-mic) | NodeCreated (exists getData) | 無 |
delete(/ zk-persis-mic) | NodeDeleted (exists getData) | 無 |
setData(/ zk-persis-mic) | NodeDataChanged (exists getData) | |
create(/ zk-persis-mic/child) | NodeChildrenChange(getChildren) | NodedCreated |
delete(/ zk-persis-mic/child) | NodeChildrenChange(getChildren) | NodedDeleted |
setData(/ zk-persis-mic/child) | NodeDataChanged |
3 Curator 客戶端的使用,簡單高效
3.1使用Curator對zookeeper增刪改查
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;
/**
* @author: xiepanpan
* @Date: 2020/5/31
* @Description: 使用Curator框架來對zookeeper操作
*/
public class CuratorDemo {
public static void main(String[] args) throws Exception {
CuratorFramework curatorFramework = CuratorFrameworkFactory
.builder()
//衰減的重試機制
.retryPolicy(new ExponentialBackoffRetry(1000,3))
.connectString("192.168.217.130:2181,192.168.217.130:2183,192.168.217.130:2183")
.sessionTimeoutMs(4000)
//隔離命名空間 以下所有操作都是基於該相對目錄進行的
.namespace("curator")
.build();
curatorFramework.start();
//創建節點
//結果 /curator/xpp/mode1
curatorFramework.create()
.creatingParentsIfNeeded()
.withMode(CreateMode.PERSISTENT)
.forPath("/xpp/node1","1".getBytes());
//更改節點
//保存節點狀態
Stat stat = new Stat();
curatorFramework.getData().storingStatIn(stat).forPath("/xpp/node1");
curatorFramework.setData().withVersion(stat.getVersion()).forPath("/xpp/node1","xx".getBytes());
//刪除節點
curatorFramework.delete().deletingChildrenIfNeeded().forPath("/xpp/node1");
}
}
3.2 監聽
PathChildrenCache 監聽一個節點下的子節點的創建刪除和更新
NodeCache監聽一個節點的更新和創建事件
TreeCache 綜合PathChildrenCache 和NodeCache 的特性
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.*;
import org.apache.curator.retry.ExponentialBackoffRetry;
/**
* @author: xiepanpan
* @Date: 2020/5/31
* @Description: 事件監聽
*/
public class CuratorWatcherDemo {
public static void main(String[] args) throws Exception {
CuratorFramework curatorFramework = CuratorFrameworkFactory
.builder()
//衰減的重試機制
.retryPolicy(new ExponentialBackoffRetry(1000,3))
.connectString("192.168.217.130:2181,192.168.217.130:2183,192.168.217.130:2183")
.sessionTimeoutMs(4000)
//隔離命名空間 以下所有操作都是基於該相對目錄進行的
.namespace("curator")
.build();
curatorFramework.start();
// addListenerWithNodeCache(curatorFramework,"/xpp");
// addListenerWithPathChildCache(curatorFramework,"/xpp");
addListenerWithTreeCache(curatorFramework,"/xpp");
System.in.read();
}
/**
* 監聽一個節點的更新和創建事件
* @param curatorFramework
* @param path
* @throws Exception
*/
public static void addListenerWithNodeCache(CuratorFramework curatorFramework,String path) throws Exception {
//第三個參數 對詳細內容數據的壓縮
final NodeCache nodeCache = new NodeCache(curatorFramework,path,false);
NodeCacheListener nodeCacheListener = new NodeCacheListener() {
public void nodeChanged() throws Exception {
System.out.println("Receive Event:"+nodeCache.getCurrentData().getPath());
}
};
nodeCache.getListenable().addListener(nodeCacheListener);
nodeCache.start();
}
/**
* 監聽一個節點子節點的創建刪除和更新
* @param curatorFramework
* @param path
* @throws Exception
*/
public static void addListenerWithPathChildCache(CuratorFramework curatorFramework,String path) throws Exception {
PathChildrenCache pathChildrenCache = new PathChildrenCache(curatorFramework, path, true);
PathChildrenCacheListener pathChildrenCacheListener = new PathChildrenCacheListener() {
public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception {
System.out.println("Receive Event:"+pathChildrenCacheEvent.getType());
}
};
pathChildrenCache.getListenable().addListener(pathChildrenCacheListener);
pathChildrenCache.start(PathChildrenCache.StartMode.NORMAL);
}
/**
* 綜合節點監聽事件 監聽當前節點和子節點 節點上任何一個事件都能收到
* @param curatorFramework
* @param path
* @throws Exception
*/
public static void addListenerWithTreeCache(CuratorFramework curatorFramework,String path) throws Exception {
TreeCache treeCache = new TreeCache(curatorFramework,path);
TreeCacheListener treeCacheListener = new TreeCacheListener() {
public void childEvent(CuratorFramework curatorFramework, TreeCacheEvent treeCacheEvent) throws Exception {
System.out.println(treeCacheEvent.getType()+"->"+treeCacheEvent.getData().getPath());
}
};
treeCache.getListenable().addListener(treeCacheListener);
treeCache.start();
}
}
我的pom文件
<!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.5.4-beta</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-framework -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.7.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-recipes -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.7.1</version>
</dependency>
zookeeper 我是用的3.4.14 版本
注意 Curator 版本 和zookeeper版本有對應關係 我的Curator版本是2.7.1
https://blog.csdn.net/glory1234work2115/article/details/51967507