zookeeper JavaAPI操作
目录
一、项目创建
1.导入依赖
<!--curator依赖-->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.10.0</version>
</dependency>
二、操作API
1.连接zookeeper
方式一
//1.第一种方式
RetryPolicy retryPolicy=new ExponentialBackoffRetry(3000,5);
/*
* @param connectString 连接字符串 zk的地址和端口 "192.168.1.1:2181" 多个zk服务用逗号隔开
* @param sessionTimeoutMs 会话超时时间(ms),客户端于zk会话中的超时时间
* @param connectionTimeoutMs 连接超时时间
* @param retryPolicy 重试策略
*/
//创建客户端
CuratorFramework client = CuratorFrameworkFactory.newClient("47.96.150.204:2181", retryPolicy);
//开启连接
client.start();
方式二
//2.第二种方式
CuratorFramework client = CuratorFrameworkFactory.builder().connectString("47.96.150.204:2181")
.sessionTimeoutMs(60 * 1000)
.connectionTimeoutMs(15 * 1000)
.retryPolicy(retryPolicy).namespace("drl").build();
client.start();
2.添加节点
2.1 添加不带数据的节点
//创建不带有数据的节点
//注意:
// 1.虽然创建时没有添加数据,但会默认生成数据,为客户端本机的ip
// 2.虽然没有指定类型,但是其创建的节点是持久化类型
public void createTest() throws Exception {
//设置不带有数据的节点
client.create().forPath("/test1");
}
2.2 添加带数据的节点
//创建带有数据的节点
//注意:
// 1.数据是以二进制传输的,需要转换
// 2.虽然没有指定类型,但是其创建的节点是持久化类型
public void createTest() throws Exception {
//设置带有数据的节点
client.create().forPath("/test2","data".getBytes());
}
2.3 添加带有数据且设置节点类型的节点
//设置临时节点类型
//注意:
// 1.设置临时节点,会导致当前会话结束之后,即这个方法结束之后,临时节点就删除
public void createTest() throws Exception {
//设置带有数据且节点类型为临时的节点
String path=client.create().withMode(CreateMode.EPHEMERAL).forPath("/test3","data".getBytes());
System.out.println(path);
}
2.4 创建多级节点
//当父节点未创建时,子节点是无法创建的
public void createTest() throws Exception {
//此时/test4节点并未创建,所以创建test5节点会报错
String path=client.create()
.withMode(CreateMode.EPHEMERAL).forPath("/test4/test5","data".getBytes());
System.out.println(path);
}
//但是在Java API当中,有一个方法,在其父节点未创建也可也创建子节点
public void createTest() throws Exception {
//创建多级节点
String path=client.create().creatingParentsIfNeeded().forPath("/test4/test5","data".getBytes());
System.out.println(path);
}
3.查询操作
3.1 查询数据
//查询数据
public void queryTest() throws Exception {
byte[] data = client.getData().forPath("/test1");
System.out.println(new String(data));
}
3.2 查询子节点
//查询子节点
public void queryTest() throws Exception {
//path="/",表示根目录下的子节点
List<String> list = client.getChildren().forPath("/");
for (String s : list) {
System.out.println(s);
}
}
3.3 查询节点状态信息
//查询节点状态信息
public void queryTest() throws Exception {
Stat status = new Stat();
client.getData().storingStatIn(status).forPath("/test1");
System.out.println(status);
}
4.修改节点
4.1 修改数据
//修改节点数据
//注意:
// 1.根据版本号进行修改
// 2.先获取版本号,然后根据版本号修改
// 若查询的版本号和修改时版本号不同,则修改失败
// 若查询的版本号和修改时版本号相同,则修改成功,dataVersion增1
//即:查询版本号 && 修改这个版本的数据 这两个操作是原子性的
public void setTest() throws Exception {
//1.先查询数据的版本
Stat stat = new Stat();
client.getData().storingStatIn(stat).forPath("/test1");
int version=stat.getVersion();
//2.根据version修改数据
client.setData().withVersion(version).forPath("/test1", "newData".getBytes());
}
5.删除节点
5.1 删除单个节点
//删除单个节点
public void deleteTest() throws Exception {
client.delete().forPath("/test1");
}
5.2 删除父节点
//在客户端删除父节点是直接删除不了的
//Java API提供了删除父节点的方法,即删除了父节点,也会将其下的子节点一并删除
public void deleteTest() throws Exception {
client.delete().deletingChildrenIfNeeded().forPath("/test1");
}
5.3 重试删除节点
//在一些特点场景下,必须删除节点成功,但由于网络原因等可能会导致删除失败,就需要重试
//可以使用guaranteed()方法,若删除失败,则进行重试,直到删除成功
public void deleteTest() throws Exception {
client.delete().guaranteed().forPath("/test1");
}
5.4 回调
//绑定一个函数,删除成功之后,就会调用这个回调函数
public void deleteTest() throws Exception {
client.delete().guaranteed().inBackground(new BackgroundCallback() {
@Override
public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
System.out.println("已删除");
}
}).forPath("/test1");
}
3.watch事件监听
watch事件监听,用户可以在节点上注册监听,当特定事件触发时,就会通知其他关注这个节点的用户。
- NodeCache:只是监听某一个特定的节点
- PathChildrenCache:监控一个ZNode的子节点(不包括自身节点)
- TreeCache:可以监控整个树上的所有节点(即NodeCache和PathChildrenaCache的组合)
3.1 NodeCache
//使用NodeCache事件监听
//注意:这块需要加入while死循环,防止这个方法执行完之后结束
public void watchTest() throws Exception {
//1.创建NodeCache对象
NodeCache nodeCache = new NodeCache(client, "/test1");
//2.注册监听
nodeCache.getListenable().addListener(new NodeCacheListener() {
@Override
public void nodeChanged() throws Exception {
System.out.println("节点发生改变了....");
//获取修改后的数据
byte[] data = nodeCache.getCurrentData().getData();
System.out.println(new String(data));
}
});
//3.开启监听
//如果设置为true,则开启监听,加载缓冲数据
nodeCache.start(true);
while (true){}
}
3.2 PathChildrenCache
//监听某个节点的所有子节点,但不会监听节点本身
public void watchTest() throws Exception {
PathChildrenCache pathChildrenCache = new PathChildrenCache(client,"/",true);
pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() {
@Override
public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception {
System.out.println("子节点变化了");
//可以根据event获取到节点改变的类型、数据等信息
System.out.println(pathChildrenCacheEvent);
//1.获取子节点改变的类型
PathChildrenCacheEvent.Type type = pathChildrenCacheEvent.getType();
//2.判断类型是否为update
if(type.equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)){
//获取更改后的数据
byte[] data = pathChildrenCacheEvent.getData().getData();
System.out.println(data);
}
}
});
pathChildrenCache.start();
while (true){}
}
3.3 TreeCache
//监听指定的节点及子节点,相当于NodeCache与PathChildrenCache的合集
public void watchTest() throws Exception {
TreeCache treeCache = new TreeCache(client,"/");
treeCache.getListenable().addListener(new TreeCacheListener() {
@Override
public void childEvent(CuratorFramework curatorFramework, TreeCacheEvent treeCacheEvent) throws Exception {
//1.获取改变类型
TreeCacheEvent.Type type = treeCacheEvent.getType();
//2.判断改变类型
if(type.equals(TreeCacheEvent.Type.NODE_UPDATED)){
System.out.println(treeCacheEvent.getData().getData());
}
}
});
treeCache.start();
while (true){}
}