Curator是Zookeeper的Java客户端库,官网为 https://curator.apache.org

环境

  • Ubuntu 22.04
  • Zookeeper 3.7.1
  • JDK 17.0.3.1
  • IntelliJ IDEA 2022.1.3
  • Curator 5.4.0

准备

创建Maven项目 test1215

打开 pom.xml 文件,添加如下依赖:

        <!-- https://mvnrepository.com/artifact/org.apache.curator/curator-recipes --><dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>5.4.0</version></dependency><!-- https://mvnrepository.com/artifact/org.apache.curator/curator-framework --><dependency><groupId>org.apache.curator</groupId><artifactId>curator-framework</artifactId><version>5.4.0</version></dependency><!-- https://mvnrepository.com/artifact/junit/junit --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency>

src/test/java 目录下,创建测试文件 Test1215.java

首先加上连接和关闭连接的测试:

package pkg1;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.junit.After;
import org.junit.Before;
import org.junit.Test;public class Test1215 {private CuratorFramework client;@Beforepublic void testConnect() {RetryPolicy retryPolicy = new ExponentialBackoffRetry(3000, 10);client = CuratorFrameworkFactory.builder().connectString("localhost:2181").sessionTimeoutMs(60 * 1000).connectionTimeoutMs(15 * 1000).retryPolicy(retryPolicy).namespace("test1215").build();client.start();}// quit@Afterpublic void testClose() {if (client != null) {client.close();}}

注:

  • 本例是单机Zookeeper,所以connectionString是 localhost:2181 ,如果是Zookeeper集群,则connectionString是 localhost:2181,localhost:2182,localhost:2183 这样的。
  • 在创建连接时,指定了namespace为 test1215 ,表示所有的操作都是在 /test1215 节点下操作的,否则默认是在根节点 / 下操作的。

增删改查操作

创建节点

    // create <node>@Testpublic void test1() throws Exception {client.create().forPath("/app1");}

运行测试,然后在命令行下查看:

ls /
[test1, test1215, test20000000003, test20000000004, test30000000005, zookeeper]
ls /test1215
[app1]

可见,创建了节点 /test1215/test1215/app1

get /test1215/app1
127.0.1.1

注意,如果不设置数据,默认会设置为机器的IP地址,即 127.0.0.1

若要显式设置数据,则 forPath() 方法需要多一个参数。

    // create <node> <data>@Testpublic void test2() throws Exception {client.create().forPath("/app2", "Hello".getBytes());}

若要设置节点的临时性和顺序性,则要用 withMode() 方法:

    // create -es <node>@Testpublic void test3() throws Exception {client.create().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath("/app3");}

本例中创建了一个临时且顺序的节点。

注意,会话结束后,临时节点就会自动删除,所以要验证的话,需要设置断点,让程序暂停,然后在命令行下查看:

ls /test1215
[app1, app2, app30000000002]

可见,创建了顺序节点 app30000000002

等运行结束后再查看:

ls /test1215
[app1, app2]

可见,临时节点在会话结束之后自动删除了。

如果需要一次性创建多级节点,则要用 creatingParentsIfNeeded() 方法:

    // create <parent>// create <parent/child>@Testpublic void test4() throws Exception {client.create().creatingParentsIfNeeded().forPath("/app4/child1");client.create().creatingParentsIfNeeded().forPath("/app4/child2/aaa");}

注:貌似没有对应的命令,Curator可能是一级一级创建的。

运行测试,然后在命令行下查看:

ls /test1215
[app1, app2, app4]
ls /test1215/app4
[child1, child2]
ls /test1215/app4/child2
[aaa]

注意:默认的数据 127.0.0.1 是设置在最小的节点上的,本例中为 /test1215/app4/child1/test1215/app4/child2/aaa

查询节点

获取节点数据:

    // get <node>@Testpublic void test5() throws Exception {byte[] data = client.getData().forPath("/app2");String str = new String(data);System.out.println(str);}

运行结果如下:

Hello

查询子节点:

    // ls <node>@Testpublic void test6() throws Exception {List<String> list = client.getChildren().forPath("/");list.forEach(System.out::println);}

运行结果如下:

app2
app1
app4

注意:这里的 / 实际上是 /test1215 ,因为设置了namespace。

查询节点状态:

    // ls -s <node>@Testpublic void test7() throws Exception {Stat stat = new Stat();System.out.println(stat);client.getData().storingStatIn(stat).forPath("/app2");System.out.println(stat);}

运行结果如下:

0,0,0,0,0,0,0,0,0,0,0103,103,1671156504367,1671156504367,0,0,0,0,5,0,103

设置节点数据

直接更新节点数据:

    // set <node> <data>@Testpublic void test8() throws Exception {client.setData().forPath("/app2", "China".getBytes());}

运行测试,然后在命令行下查看:

get /test1215/app2
China

根据版本号更新数据:

    // set -v <version> <node> <data>@Testpublic void test9() throws Exception {Stat stat = new Stat();client.getData().storingStatIn(stat).forPath("/app2");int version = stat.getVersion();System.out.println("Version = " + version);client.setData().withVersion(version).forPath("/app2", "good".getBytes());
//        client.setData().withVersion(100).forPath("/app2", "good".getBytes());}

运行结果如下:

Version = 1

注意:本例中,先获取节点的版本,在更新数据时,带上该版本号,以确保没有并发问题。如果此时实际的版本号已改变,二者不相等,则不会更新数据,而是抛出异常。

更新成功后版本号会加1。本例中,原先的版本号为1,如果更新成功,则版本号会变成2。

在命令行验证版本号:

ls -s /test1215/app2
[]
cZxid = 0x67
ctime = Fri Dec 16 10:08:24 CST 2022
mZxid = 0x80
mtime = Fri Dec 16 10:25:16 CST 2022
pZxid = 0x67
cversion = 0
dataVersion = 2
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0

可见,当前的 dataVersion 已经变为2。

如果更新时,获取的版本号和实际版本号不相等(本例中可用硬编码来指定一个错误的版本号),则会报错:

org.apache.zookeeper.KeeperException$BadVersionException: KeeperErrorCode = BadVersion for /test1215/app2

删除节点

删除没有子节点的节点:

    // delete <node>@Testpublic void test10() throws Exception {client.delete().forPath("/app1");}

运行测试,然后在命令行下查看:

ls /test1215
[app2, app4]

可见 /test1215/app1 已经删除了。

删除带有子节点的节点:

    // deleteall <node>@Testpublic void test11() throws Exception {client.delete().deletingChildrenIfNeeded().forPath("/app4/child2");}

运行测试,然后在命令行下查看:

ls /test1215/app4
[child1]

可见, /test1215/app4/child2 连同其子节点 /test1215/app4/child2/aaa 一起删除了。

确保删除成功:

    // delete <node>@Testpublic void test12() throws Exception {client.delete().guaranteed().forPath("/app4/child1");}

运行测试,然后在命令行下查看:

ls /test1215/app4
[]

本例中看不出 guaranteed() 的效果。

可以在删除节点时,添加一个回调函数:

    // delete <node>@Testpublic void test13() throws Exception {client.delete().inBackground(new BackgroundCallback() {@Overridepublic void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {System.out.println("Deleted");System.out.println(curatorEvent);}}).forPath("/app2");}

运行结果如下:

Deleted
CuratorEventImpl{type=DELETE, resultCode=0, path='/app2', name='null', children=null, context=null, stat=null, data=null, watchedEvent=null, aclList=null, opResults=null}

在命令行下查看:

[zk: localhost:2181(CONNECTED) 107] ls /test1215
[app4]

可见 /test1215/app2 已经删除了。

注意,此时如果把 /test1215/app4 删除,则 /test1215 节点为空,大概几秒钟后也就自动删除了。但是刚才把 /test1215/app4 下的所有子节点都删除之后, /test1215/app4 节点为空,并不会自动删除。可见用namespace创建的节点有一个特性:当其为空时,就会自动删除。这应该也是封装的Zookeeper的特性吧,有待研究。

Curator基本操作(Zookeeper节点增删改查)相关推荐

  1. 自定义 RPC框架3——JAVA实现Zookeeper节点增删改查

    Zookeeper安装 zookeeper的安装在之前的文章中已经写过:https://blog.csdn.net/qq_45587153/article/details/123630361?spm= ...

  2. ZooKeeper【基础 02】zookeeper-3.6.0 常用Shell命令(节点增删改查+监听器+四字指令)

    我使用的安装文件是 apache-zookeeper-3.6.0-bin.tar.gz ,以下内容均以此版本进行说明.这个是官网的3.6.0<CLI命令说明> 感兴趣的可以查看. 1.1 ...

  3. ZooKeeper【基础知识 02】zookeeper-3.6.0 常用Shell命令(节点增删改查+监听器+四字指令)

    我使用的安装文件是 apache-zookeeper-3.6.0-bin.tar.gz ,以下内容均以此版本进行说明.这个是官网的3.6.0<CLI命令说明> 感兴趣的可以查看. 1.1 ...

  4. JS DOM节点增删改查 属性设置

    一.节点操作 增 createElement(name)创建元素 appendChild();将元素添加 删 获得要删除的元素 获得它的父元素 使用removeChild()方法删除 改 第一种方式: ...

  5. Zookeeper JavaApi 增删改查

    官网API http://zookeeper.apache.org/doc/r3.4.6/api/index.html JAR包 \zookeeper-3.3.6\lib\ jline-0.9.94. ...

  6. Zookeeper后端开发工具Curator的使用 | Curator对节点的增删改查 | ACL权限控制 | 分布式锁 | 分布式计数器 | 附带最新版本下载

    前言 Curator是Apache开源的一个Java工具类,通过它操作Zookeeper会变得极度舒适! 前置条件:已掌握的基本操作,比如在后台可以增减节点.ACL权限设置等. 1.Zookeeper ...

  7. zookeeper curator客户端之增删改查

    zookeeper curator客户端之增删改查 zookeeper安装:https://www.cnblogs.com/zwcry/p/10272506.html curator客户端是Apach ...

  8. Zookeeper 客户端API调用示例(基本使用,增删改查znode数据,监听znode,其它案例,其它网络参考资料)

    9.1 基本使用 org.apache.zookeeper.Zookeeper是客户端入口主类,负责建立与server的会话 它提供以下几类主要方法  : 功能 描述 create 在本地目录树中创建 ...

  9. zkcli远程连接_ZooKeeper客户端 zkCli.sh 节点的增删改查

    zkCli.sh 在 bin 目录下的  zkCli.sh  就是ZooKeeper客户端 ./zkCli.sh -timeout 5000  -server 127.0.0.1:2181  客户端与 ...

最新文章

  1. 功能性平台创新-农业大健康·杨建国:谋定都江堰精华灌区
  2. java调用本地shell_java通过ProcessBuilder执行本地shell命令 获取ip配置信息
  3. Excel快速改变行列的次序
  4. 2017蓝桥杯省赛---java---C---2(兴趣小组)
  5. activiti5.22 springboot 流程引擎 实战全过程
  6. 遵义大数据中心项目工程概况_市委书记张新文到曹州云都大数据中心等项目现场调研建设情况...
  7. Django中示例验证码的实现总结
  8. 在php中使用CKEDITOR在线编辑器
  9. python 二分查找_LeetCode基础算法题第120篇:二分查找算法
  10. 事务的acid属性是指_Mysql事务的性质 为什么要用事务?
  11. x射线计算机断层成像_医疗保健中的深度学习-X射线成像(第4部分-类不平衡问题)...
  12. 加载八叉树索引文件_mysql innodb索引原理
  13. 【备忘】年薪50万2017年最新北风网Spark2.0从入门到精通教程
  14. 记一次有惊无险的 JVM 优化经历
  15. qiankun 出现[import-html-entry]: error occurs while executing normal script
  16. BZOJ4567[Scoi2016]背单词
  17. 图像处理——人脸情绪识别(python卷积神经网络)
  18. Twitter新任80后印度裔CEO,为啥是他?
  19. Windows10文件后缀名不显示·解决方法
  20. Vue 利用后端的数据字典和Map对象实现表格列字段动态转义的处理方案

热门文章

  1. 把Form转换成TXT格式的文件
  2. convs在MATLAB中,matlab2_MATELAB课程设计_ppt_大学课件预览_高等教育资讯网
  3. 从val_loss,train_loss,test_loss中产生的问题
  4. STM32液晶显示中英文
  5. dhcp二层中继和三层中继
  6. 对苹果maccms网站漏洞进行修复解决过程
  7. 机车安装鸿蒙系统,华为鸿蒙系统2.0版本来了:9月11日发布 打通PC、手表、车机等...
  8. html表格突出显示,java-如何突出显示jtable单元格的文本?
  9. java斗地主发牌_实现斗地主发牌(java)
  10. 计算机系统仿真缩写,仿真语言