一.概述
znode是zookeeper集合的核心组件,zookeeper API提供了一小组方法使用zookeeper集合来操纵znode的所有细节。
客户端应该遵循以下步骤,与zookeeper服务器进行清晰和干净的交互。
- 连接到zookeeper服务器。zookeeper服务器为客户端分配会话ID。
- 定期向服务器发送心跳。否则,zookeeper服务器将过期会话ID,客户端需要重新连接。
- 只要会话ID处于活动状态,就可以获取/设置znode。
- 所有任务完成后,断开与zookeeper服务器的连接。如果客户端长时间不活动,则zookeeper服务器将自动断开客户端。
二.连接到zookeeper服务器
1.连接zookeeper的语法
Zookeeper(String connectionString,int sessionTimeout,Watcher watcher)
- connectionString-zookeeper主机
- sessionTimeout-会话超时(以毫秒为单位)
- watcher-实现"监视器"对象。zookeeper集合通过监视器对象返回连接状态。
2.演示
(1)代码块
package com.fengmo.zookeeper;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import java.util.concurrent.CountDownLatch;
public class ZookeeperConnection {
public static void main(String[] args) {
try{
//计数器对象
CountDownLatch countDownLatch = new CountDownLatch(1);
//1.创建连接zookeeper服务器对象
//参数一是zookeeper服务器地址和端口,参数二是连接超时时间,参数三是监视器对象
ZooKeeper zooKeeper = new ZooKeeper(
"192.168.83.134:2181", 5000, new Watcher() {
@Override
public void process(WatchedEvent event) {
//2.判断是否创建成功
if(event.getState()==Event.KeeperState.SyncConnected){
System.out.println("当状态码符合条件,创建成功");
countDownLatch.countDown(); //唤醒主线程
}
}
});
//主线程阻塞等待连接对象的创建成功
countDownLatch.await();
//3.打印会话id
System.out.println("会话id是" + zooKeeper.getSessionId());
//4.释放资源
zooKeeper.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
(2)范例
3.源码
三.新增节点
1.语法
//同步方式
create(String path,byte[] data,List<ACL> acl,CreateMode createMode)
//异步方式
create(String path,byte[] data,List<ACL> acl,CreateMode createMode,
AsyncCallback.StringCallback callBack,Object ctx)
- path-znode路径,例如,/node1/node11
- data-要存储在指定znode路径中的数据。
- acl-要创建的节点的访问控制列表。zookeeper API提供了一个静态接口ZooDefs.Ids来获取一些基本的acl列表,例如,ZooDefs.Ids.OPEN_ACL_UNSAFE返回打开znode的acl列表。
- createMode-节点的类型,这是一个枚举。
- callBack-异步回调接口。
- ctx-传递上下文参数。
2.演示
(1)全局的建立连接zookeeper服务器方法【准备工作】
(1-1)代码块
@Before
//创建zookeeper的连接
public void before()throws Exception{
//计数器对象
CountDownLatch countDownLatch = new CountDownLatch(1);
//1.创建连接zookeeper服务器对象
//参数一是zookeeper服务器地址和端口,参数二是连接超时时间,参数三是监视器对象
zooKeeper = new ZooKeeper(IP, 5000, new Watcher() {
@Override
public void process(WatchedEvent event) {
//2.判断是否创建成功
if(event.getState()==Event.KeeperState.SyncConnected){
System.out.println("当状态码符合条件,创建成功");
countDownLatch.countDown(); //唤醒主线程
}
}
});
//主线程阻塞等待连接对象的创建成功
countDownLatch.await();
}
(1-2)范例
(2)全局关闭资源的方法【准备工作】
(2-1)代码块
@After
//释放资源
public void after()throws Exception{
zooKeeper.close();
}
(2-2)范例
(3)同步创建节点
(3-1)代码块
@Test
//增删改查的节点操作,【同步创建节点】
public void create1()throws Exception{
zooKeeper.create(
"/node1/node81", //节点的路径
"node1".getBytes(), //节点的数据
ZooDefs.Ids.OPEN_ACL_UNSAFE, //权限列表,world:anyone:cdrwa
CreateMode.PERSISTENT); //节点类型:持久化节点
}
(3-2)范例
(4)同步创建节点并设置只读权限
(4-1)代码块
@Test
//增删改查的节点操作,【同步创建节点】【设置只读权限】
public void create2()throws Exception{
zooKeeper.create(
"/node1/node82", //节点的路径
"node1".getBytes(), //节点的数据
ZooDefs.Ids.READ_ACL_UNSAFE, //权限列表,world:anyone:r 设置只读权限
CreateMode.PERSISTENT); //节点类型:持久化节点
}
(4-2)范例
(5)同步创建节点并设置权限列表
(5-1)代码块
@Test
//增删改查的节点操作,【同步创建节点】【设置权限列表】
public void create3()throws Exception{
//world授权模式
//1.权限列表
List<ACL> acls = new ArrayList<ACL>();
//2.授权模式和授权对象
Id id = new Id("world","anyone");
//3.权限设置
acls.add(new ACL(ZooDefs.Perms.READ,id)); //读权限
acls.add(new ACL(ZooDefs.Perms.WRITE,id)); //写权限
//4.创建节点
zooKeeper.create("/node1/node83","node1".getBytes(),acls,CreateMode.PERSISTENT);
}
(5-2)范例
(6)同步创建节点并ip授权模式
(6-1)代码块
@Test
//增删改查的节点操作,【同步创建节点】【ip授权】
public void create4()throws Exception{
//ip授权
//1.权限列表
List<ACL> acls = new ArrayList<ACL>();
//2.授权模式和授权对象
Id id = new Id("ip","192.168.83.134");
//3.权限设置
acls.add(new ACL(ZooDefs.Perms.ALL,id)); //所有权限
//4.创建节点
zooKeeper.create("/node1/node84","node1".getBytes(),acls,CreateMode.PERSISTENT);
}
(6-2)范例
(7)同步创建节点并auth授权模式
(7-1)代码块
@Test
//增删改查的节点操作,【同步创建节点】【auth授权模式】
public void create5()throws Exception{
//auth授权模式
//添加授权用户
//参数一是授权模式,参数二是用户名和密码,用:分割。
zooKeeper.addAuthInfo("digest","user2:userpassword2".getBytes());
//4.创建节点
zooKeeper.create("/node1/node85","node1".getBytes(),ZooDefs.Ids.CREATOR_ALL_ACL,CreateMode.PERSISTENT);
}
(7-2)范例
(8)同步创建节点并设置指定用户指定节点的访问权限
(8-1)代码块
@Test
//增删改查的节点操作,【同步创建节点】【auth授权模式】【指定认证用户指定节点的访问权限】
public void create6()throws Exception{
//auth授权模式
//1.添加授权用户
//参数一是授权模式,参数二是用户名和密码,用:分割。
zooKeeper.addAuthInfo("digest","user2:userpassword2".getBytes());
//2.权限列表
List<ACL> acls = new ArrayList<ACL>();
//3.授权模式和授权对象
Id id = new Id("auth","user2");
//4.权限设置
acls.add(new ACL(ZooDefs.Perms.READ,id)); //设置user2用户访问权限为只读
//5.创建节点
zooKeeper.create("/node1/node86","node1".getBytes(),acls,CreateMode.PERSISTENT);
}
(8-2)范例
(9)同步创建节点并加密授权模式
(9-1)代码块
//增删改查的节点操作,【同步创建节点】【digest授权模式】
@Test
public void create7()throws Exception{
//digest模式
//1.权限列表
List<ACL> acls = new ArrayList<ACL>();
//3.授权模式和授权对象
Id id = new Id("digest","user3:HOzyzzJq3lZmwrnPfLK9voz7DrY=");
//4.权限设置
acls.add(new ACL(ZooDefs.Perms.ALL,id));
//5.创建节点
zooKeeper.create("/node1/node87","node1".getBytes(),acls,CreateMode.PERSISTENT);
}
(9-2)范例
(10)同步创建节点并设置持久化顺序节点
(10-1)代码块
//增删改查的节点操作,【同步创建节点】【持久化顺序节点】
@Test
public void create8()throws Exception{
//创建节点 Ids.OPEN_ACL_UNSAFE world:anyone:cdrwa
String result = zooKeeper.create(
"/node1/node88",
"node1".getBytes(),
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT_SEQUENTIAL);
//该返回值是该节点路径
System.out.println(result);
}
(10-2)范例
(11)同步创建节点并设置临时节点
(11-1)代码块
//增删改查的节点操作,【同步创建节点】【临时节点】
@Test
public void create9()throws Exception{
//创建节点 Ids.OPEN_ACL_UNSAFE world:anyone:cdrwa
String result = zooKeeper.create(
"/node1/node89",
"node1".getBytes(),
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL);
//注意事项:该访问连接资源关闭,则临时节点不存在
//该返回值是该节点路径
System.out.println(result);
}
(11-2)范例
(12)同步创建节点并设置临时有序节点
(12-1)代码块
//增删改查的节点操作,【同步创建节点】【临时有序节点】
@Test
public void create10()throws Exception{
//创建节点 Ids.OPEN_ACL_UNSAFE world:anyone:cdrwa
String result = zooKeeper.create(
"/node1/node90",
"node1".getBytes(),
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL_SEQUENTIAL);
//注意事项:该访问连接资源关闭,则临时节点不存在
//该返回值是该节点路径
System.out.println(result);
}
(12-2)范例
(13)异步创建节点
(13-1)代码块
//增删改查的节点操作,【异步请求创建节点】
@Test
public void create11()throws Exception{
//创建节点 Ids.OPEN_ACL_UNSAFE world:anyone:cdrwa
zooKeeper.create(
"/node1/node91", "node1".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL,
new AsyncCallback.StringCallback() {
@Override
public void processResult(int rc, String path, Object ctx, String name) {
//0.代表创建成功
System.out.println(rc);
//节点的路径
System.out.println(path);
//节点的路径
System.out.println(name);
//上下文参数,将客户端的ctx("I am context")传给zookeeper服务器
System.out.println(ctx);
}
},"I am context");
Thread.sleep(10000);
System.out.println("结束");
}
(13-2)范例
3.源码
四.更新节点
1.语法
//同步方式
setData(String path,byte[] data,int version)
//异步方式
setData(String path,byte[] data,int version,AsynCallback.statCallback callBack,Object ctx)
- path-znode路径。
- data-要存储在指定znode路径中的数据。
- version-znode的当前版本。每当数据更改时,Zookeeper会更新znode的版本号。
- callBack-异步回调接口。
- ctx-传递上下文参数。
2.演示
(1)连接zookeeper服务器【准备工作】
(1-1)代码块
@Before
//创建zookeeper的连接
public void before()throws Exception{
//计数器对象
CountDownLatch countDownLatch = new CountDownLatch(1);
//1.创建连接zookeeper服务器对象
//参数一是zookeeper服务器地址和端口,参数二是连接超时时间,参数三是监视器对象
zooKeeper = new ZooKeeper(IP, 5000, new Watcher() {
@Override
public void process(WatchedEvent event) {
//2.判断是否创建成功
if(event.getState()==Event.KeeperState.SyncConnected){
System.out.println("当状态码符合条件,创建成功");
countDownLatch.countDown(); //唤醒主线程
}
}
});
//主线程阻塞等待连接对象的创建成功
countDownLatch.await();
}
(1-2)范例
(2)关闭资源【准备工作】
(2-1)代码块
@After
//释放资源
public void after()throws Exception{
zooKeeper.close();
}
(2-2)范例
(3)同步修改节点数据【不更新节点版本号】
(3-1)代码块
@Test
//不修改版本的修改指定节点的数据【同步】
public void set1()throws Exception{
//参数一:节点的路径,参数二:修改的数据,参数三:数据版本号。-1代表版本号不参与更新
zooKeeper.setData("/node2/node21","node111".getBytes(),-1);
}
(3-2)范例
(4)同步修改节点数据【更新节点版本号】
(4-1)代码块
@Test
//修改指定版本的指定节点的数据【同步】
public void set2()throws Exception{
/*
cZxid = 0x87
ctime = Thu Jan 21 09:11:06 CST 2021
mZxid = 0x8a
mtime = Thu Jan 21 09:17:01 CST 2021
pZxid = 0x87
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 7
numChildren = 0
*/
//参数一:节点的路径,参数二:修改的数据,参数三:数据版本号。
zooKeeper.setData("/node2/node21","node222".getBytes(),1); //需要dataVersion一致
}
(4-2)范例
(5)异步请求修改节点数据
(5-1)代码块
@Test
//修改版本的节点数据【异步】
public void test3()throws Exception{
zooKeeper.setData("/node2/node22","node224".getBytes(),-1, new AsyncCallback.StatCallback() {
@Override
public void processResult(int rc, String path, Object ctx, Stat stat) {
// 0代表修改成功
System.out.println(rc);
//节点的路径:path
System.out.println(path);
//上下文参数对象:ctx
System.out.println(ctx);
//属性描述对象:stat
System.out.println(stat.getVersion()); //获取版本号
}
},"I am Context!!!");
Thread.sleep(1000);
System.out.println("结束");
}
(5-2)范例
五.删除节点
1.语法
//同步方式
delete(String path,int version)
//异步请求
detlet(String path,int version,AsyncCallback.VoidCallback callBack,Object ctx)
path-znode路径。
version-znode的当前版本。
callback-异步回调接口
ctx-传递上下文参数
2.演示
(1)连接zookeeper服务器【准备工作】
(1-1)代码块
@Before
//创建zookeeper的连接
public void before()throws Exception{
//计数器对象
CountDownLatch countDownLatch = new CountDownLatch(1);
//1.创建连接zookeeper服务器对象
//参数一是zookeeper服务器地址和端口,参数二是连接超时时间,参数三是监视器对象
zooKeeper = new ZooKeeper(IP, 5000, new Watcher() {
@Override
public void process(WatchedEvent event) {
//2.判断是否创建成功
if(event.getState()==Event.KeeperState.SyncConnected){
System.out.println("当状态码符合条件,创建成功");
countDownLatch.countDown(); //唤醒主线程
}
}
});
//主线程阻塞等待连接对象的创建成功
countDownLatch.await();
}
(1-2)范例
(2)关闭资源【准备工作】
(2-1)代码块
@After
//释放资源
public void after()throws Exception{
zooKeeper.close();
}
(2-2)范例
(3)同步删除节点【不考虑版本号】
(3-1)代码块
@Test
//删除节点,但不考虑版本号。【同步】
public void delete1()throws Exception{
//参数一:节点的路径,参数二:数据版本号。-1代表版本号不参与更新
zooKeeper.delete("/delznode/node1",-1);
}
(3-2)范例
(4)同步删除节点【设置版本号】
(4-1)代码块
@Test
//删除节点,但指定版本。【同步】
public void delete2()throws Exception{
//参数一:节点的路径,参数二:数据版本号。-1代表版本号不参与更新
zooKeeper.delete("/delznode/node2",2);
}
(4-2)范例
(5)异步删除节点【不考虑版本号】
(5-1)代码块
@Test
//删除节点,但不考虑版本号。【异步】
public void delete3()throws Exception{
//参数一:节点的路径,参数二:数据版本号。-1代表版本号不参与更新
zooKeeper.delete("/delznode/node2", -1, new AsyncCallback.VoidCallback() {
@Override
public void processResult(int rc, String path, Object ctx) {
//0是删除成功
System.out.println(rc);
//节点路径 path
System.out.println(path);
//上下文参数传递ctx
System.out.println(ctx);
}
},"I am context!!!");
Thread.sleep(1000);
System.out.println("结束");
}
(5-2)范例
六.查看节点
1.语法
//同步方式
getData(String path,boolean b,Stat stat)
//异步方式
getData(String path,boolean b,AsyncCallback.DataCallback callBack,Object ctx)
path-znode路径。
b-是否使用连接对象中注册的监听器。
stat-返回znode的元数据。
callBack-异步回调接口。
ctx-传递上下文参数。
2.演示
(1)连接zookeeper服务器【准备工作】
(1-1)代码块
@Before
//创建zookeeper的连接
public void before()throws Exception{
//计数器对象
CountDownLatch countDownLatch = new CountDownLatch(1);
//1.创建连接zookeeper服务器对象
//参数一是zookeeper服务器地址和端口,参数二是连接超时时间,参数三是监视器对象
zooKeeper = new ZooKeeper(IP, 5000, new Watcher() {
@Override
public void process(WatchedEvent event) {
//2.判断是否创建成功
if(event.getState()==Event.KeeperState.SyncConnected){
System.out.println("当状态码符合条件,创建成功");
countDownLatch.countDown(); //唤醒主线程
}
}
});
//主线程阻塞等待连接对象的创建成功
countDownLatch.await();
}
(1-2)范例
(2)关闭资源【准备工作】
(2-1)代码块
@After
//释放资源
public void after()throws Exception{
zooKeeper.close();
}
(2-2)范例
(3)获取数据【同步】
(3-1)代码块
@Test
//获取数据【同步】
public void get1()throws Exception{
//参数一:节点路径。参数二:监听器,参数三:读取节点属性的对象
Stat stat = new Stat(); //创建节点信息对象
byte[] bys = zooKeeper.getData("/getnode/node1", false, stat);
//打印数据
System.out.println(new String(bys));
}
(3-2)范例
(4)获取数据【异步】
(4-1)代码块
//获取数据【异步】
@Test
public void get2()throws Exception{
//参数一:节点路径。参数二:监听器,参数三:读取节点属性
zooKeeper.getData("/getnode/node1", false, new AsyncCallback.DataCallback() {
@Override
public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat) {
//0代表读取成功
System.out.println(rc);
//节点路径
System.out.println(path);
//上下文参数对象
System.out.println(ctx);
//数据
System.out.println(new String(data));
//属性对象
System.out.println(stat.getVersion());
}
},"I am context");
Thread.sleep(10000);
System.out.println("结束");
}
(4-2)范例
七.查看子节点
1.语法
//同步方式
getChildren(String path,boolean b)
//异步方式
getChildren(String path,boolean b,AsyncCallback.childrenCallback callBack,Object ctx)
- path-Znode路径。
- b-是否使用连接对象中注册的监视器。
- callBack-异步回调接口。
- ctx-传递上下文参数。
2.演示
(1)连接zookeeper服务器【准备工作】
(1-1)代码块
@Before
//创建zookeeper的连接
public void before()throws Exception{
//计数器对象
CountDownLatch countDownLatch = new CountDownLatch(1);
//1.创建连接zookeeper服务器对象
//参数一是zookeeper服务器地址和端口,参数二是连接超时时间,参数三是监视器对象
zooKeeper = new ZooKeeper(IP, 5000, new Watcher() {
@Override
public void process(WatchedEvent event) {
//2.判断是否创建成功
if(event.getState()==Event.KeeperState.SyncConnected){
System.out.println("当状态码符合条件,创建成功");
countDownLatch.countDown(); //唤醒主线程
}
}
});
//主线程阻塞等待连接对象的创建成功
countDownLatch.await();
}
(1-2)范例
(2)关闭资源【准备工作】
(2-1)代码块
@After
//释放资源
public void after()throws Exception{
zooKeeper.close();
}
(2-2)范例
(3)获取数据【同步】
(3-1)代码块
@Test
//获取子节点【同步】
public void child1()throws Exception{
//参数一:子节点的父路径,参数二:监听器
List<String> list = zooKeeper.getChildren("/getchild",false);
for(String str : list){
System.out.println(str);
}
}
(3-2)范例
(4)获取数据【异步】
(4-1)代码块
@Test
//获取子节点【异步】
public void child2()throws Exception{
//参数一:子节点的父路径,参数二:监听器
zooKeeper.getChildren("/getchild", false, new AsyncCallback.ChildrenCallback() {
@Override
public void processResult(int rc, String path, Object ctx, List<String> children) {
// 0代表读取成功
System.out.println(rc);
//节点的路径
System.out.println(path);
//上下文参数对象
System.out.println(ctx);
//子节点信息
for (String str: children) {
System.out.println(str);
}
}
},"I am Context");
Thread.sleep(10000);
System.out.println("结束");
}
(4-2)范例
八.检查节点是否存在
1.语法
//同步方法
exits(String path,boolean b)
//异步方法
exits(String path,boolean b,AsyncCallback.StatCallback callBack,Object ctx)
path-znode路径。
b-是否使用连接对象中注册的监视器。
callBack-异步回调接口。
ctx-传递上下文参数。
2.演示
(1)连接zookeeper服务器【准备工作】
(1-1)代码块
@Before
//创建zookeeper的连接
public void before()throws Exception{
//计数器对象
CountDownLatch countDownLatch = new CountDownLatch(1);
//1.创建连接zookeeper服务器对象
//参数一是zookeeper服务器地址和端口,参数二是连接超时时间,参数三是监视器对象
zooKeeper = new ZooKeeper(IP, 5000, new Watcher() {
@Override
public void process(WatchedEvent event) {
//2.判断是否创建成功
if(event.getState()==Event.KeeperState.SyncConnected){
System.out.println("当状态码符合条件,创建成功");
countDownLatch.countDown(); //唤醒主线程
}
}
});
//主线程阻塞等待连接对象的创建成功
countDownLatch.await();
}
(1-2)范例
(2)关闭资源【准备工作】
(2-1)代码块
@After
//释放资源
public void after()throws Exception{
zooKeeper.close();
}
(2-2)范例
(3)同步查询节点是否存在
(3-1)代码块
@Test
public void exists1()throws Exception{
//参数一:节点路径。参数二:监视器。
Stat stat = zooKeeper.exists("/node1", false);
System.out.println(stat); //读取节点的状态信息,
}
(3-2)范例
(4)异步查询节点是否存在
(4-1)代码块
@Test
//异步查看节点是否存在
public void exists2()throws Exception{
//参数一:节点路径。参数二:监视器。
zooKeeper.exists("/node1", false, new AsyncCallback.StatCallback() {
@Override
public void processResult(int rc, String path, Object ctx, Stat stat) {
//0表示方法执行成功
System.out.println(rc);
//节点的路径
System.out.println(path);
//上下文参数
System.out.println(ctx);
//节点的版本信息
System.out.println(stat.getVersion());
}
},"I am context");
}