【ZooKeeper】ZooKeeper的安装和使用


ZooKeeper的安装

在文章【Spring Boot】Dubbo和Zookeeper中已经说明了zookeeper的安装,这里直接copy过来。

  1. 下载地址:http://mirror.bit.edu.cn/apache/zookeeper
    在这里插入图片描述

  2. 下载好后解压,找到bin目录下的zkServer.cmd双击运行。
    在这里插入图片描述
    报错:在这里插入图片描述

  3. 报错解决方案:

  • 没有zoo.cfg配置文件

找到conf文件下zoo_sample.cfg,这就是我们zoo.cfg的配置样本,简单操作:复制一份zoo_sample.cfg在这个目录下改名为zoo.cfg。

在这里插入图片描述

  • 找不到或无法加载主类:

下载:下面文件并解压,复制里面的lib文件到我们的apache-zookeeper-3.6.2目录下即可。
在这里插入图片描述
在这里插入图片描述

再次双击zkServer.cmd:
在这里插入图片描述

同时双击zkCli.cmd,可以看到已经连接到了
在这里插入图片描述


ZooKeeper常用shell命令

查询节点

get /hadoop 查看结点的数据和属性 stat /hadoop 查看结点的属性

新增节点

创建结点并写入数据:

create [-s] [-e] path data 其中 -s 为有序结点,-e 临时结点(默认是持久结点)

更新节点

更新结点的命令是set,可以直接进行修改,如下:

set path data [version]

删除节点

删除结点的语法如下:

delete path [version]set 方法相似,也可以传入版本号
要想删除某个结点及其所有后代结点,可以使用递归删除,命令为 rmr path

查看结点列表

ls path # 可以查看结点的列表
ls2 path # 可以查看结点的列表以及目标结点的信息
ls / # 根节点

授权的权限

权限模式:

  • IP:通过ip进行权限控制,比如设置了ip:192.168.109.133那么表示权限控制都是针对这个ip来的。
  • Digest:最常用。形如”username:password”形式的权限标识进行控制。
  • world:最开放.对所有用户开放,所有用户都不需要权限验证就可以操作ZK。可以认为这模式没啥作用
  • super:超级用户可以对ZK进行任何操作。
权限ACL简写描述
createc可以创建子结点
deleted可以删除子结点(仅下一级结点)
readr可以读取结点数据以及显示子结点列表
writew可以设置结点数据
admina可以设置结点访问控制权限列表

create、delete、read、writer、admin也就是 增、删、查、改、管理权限,这5种权限简写为 c d r w a,注意:
这五种权限中,有的权限并不是对结点自身操作的例如:delete是指对子结点的删除权限
可以试图删除父结点,但是子结点必须删除干净,所以delete的权限也是很有用的

授权命令:

命令使用方式描述
getAclgetAcl读取ACL权限
setAclsetAcl设置ACL权限
addauthaddauth添加认证用户
  • getAcl /node // 读取权限信息
  • setAcl /node world:anyone:drwa // 设置权限(禁用创建子结点的权限)
  • addauth digest <user>:<password>

JavaAPI操作ZooKeeper

znode是zooKeeper集合的核心组件,zookeeper API提供了一小组方法使用zookeeper集合来操纵znode的所有细节。

  • 客户端应该遵循以步骤,与zookeeper服务器进行清晰和干净的交互。
  • 连接到zookeeper服务器。zookeeper服务器为客户端分配会话ID。
  • 定期向服务器发送心跳。否则,zookeeper服务器将过期会话ID,客户端需要重新连接。只要会话ID处于活动状态,就可以获取/设置znode。
  • 所有任务完成后,断开与zookeeper服务器的连接。如果客户端长时间不活动,则zookeeper服务器将自动断开客户端。

环境搭配

  1. 创建一个Maven项目
  2. 导入zookeeper相应的依赖:
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.14</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

连接到zookeeper

主要使用到为我们的Zookeeper类

Zookeeper(String connectionString, int sessionTimeout, watcher watcher)
  • connectionString - zookeeper主机
  • sessionTimeout- 会话超时
  • watcher - 实现"监听器" 对象。zookeeper集合通过监视器对象返回连接状态
public class ZooKeeperConnection {

    public static void main(String[] args) {
        //计数器对象
        CountDownLatch countDownLatch = new CountDownLatch(1);
        try {
            //new ZooKeeper(服务器的ip和端口,客户端与服务器之间的会话超时时间以毫秒为单位的,监视器对象)
            ZooKeeper zooKeeper = new ZooKeeper("127.0.0.1:2181", 5000, new Watcher() {
                @Override
                public void process(WatchedEvent watchedEvent) {
                    if (watchedEvent.getState() == Watcher.Event.KeeperState.SyncConnected) {
                        System.out.println("连接成功");
                        countDownLatch.countDown();
                    }
                }
            });
            //主线程阻塞,等待连接对象创建成功
            countDownLatch.await();
            //输出会话ID
            System.out.println(zooKeeper.getSessionId());
            zooKeeper.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

新增节点

创建方式

  1. 同步方式:
  create(String path, byte[] data, List<ACL> acl, CreateMode createMode)
  1. 异步方式
  create(String path, byte[] data, List<ACL> acl, CreateMode createMode,
        AsynCallback.StringCallback callBack, Object ctx)
参数解释
pathznode路径
data数据
acl要创建的节点的访问控制列表。zookeeper API提供了一个静态接口 ZooDefs.Ids 来获取一些基本的acl列表。例如,ZooDefs.Ids.OPEN_ACL_UNSAFE返回打开znodeacl列表
createMode节点的类型,这是一个枚举, 持久结点 or 临时节点
callBack异步回调接口
ctx传递上下文参数

创建节点Java代码:

public class ZKCreate {

    ZooKeeper zooKeeper;
    String IP = "127.0.0.1:2181";

    /*
    执行顺序:Before==》Test==》After
    before:连接zookeeper
    Test:创建节点
    after:关闭zookeeper连接
     */

    @Before
    public void before() throws Exception {
        //计数器对象
        CountDownLatch countDownLatch = new CountDownLatch(1);

        //new ZooKeeper(服务器的ip和端口,客户端与服务器之间的会话超时时间以毫秒为单位的,监视器对象)
        zooKeeper = new ZooKeeper(IP, 5000, new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                if (watchedEvent.getState() == Watcher.Event.KeeperState.SyncConnected) {
                    System.out.println("连接成功");
                    countDownLatch.countDown();
                }
            }
        });

        //主线程阻塞,等待连接对象创建成功
        countDownLatch.await();

    }

    @After
    public void after() throws Exception {
        zooKeeper.close();
    }

    @Test
    public void create() throws Exception {
        //create(节点的路径,节点的数据,权限列表 worLd:anyone:cdrwa,节点类型持久化节点)
        zooKeeper.create("/node/create","hello".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
    }
}

在zkCli.cmd中创建一个/node节点,然后执行java代码,看是否会创建/node/create节点。
在这里插入图片描述
查看节点属性:
在这里插入图片描述
查看权限:world方式授权每个人anyone都有cdrwa权限
在这里插入图片描述

创建节点权限设置

  1. 先看我们前面代码创建节点的权限方式

Java代码创建节点ZooKeeper.create()
方法中的第三个参数ZooDefs.Ids.OPEN_ACL_UNSAFE表示world方式授权每个人anyone都有cdrwa权限,

我们可以修改权限参数:
查看ZooDefs 类部分源码:

public class ZooDefs {
    ......
    ......
    @Public
    public interface Ids {
        //world方式授权给每个人
        Id ANYONE_ID_UNSAFE = new Id("world", "anyone");
        //auth授权给特定的人
        Id AUTH_IDS = new Id("auth", "");
        @SuppressFBWarnings(
            value = {"MS_MUTABLE_COLLECTION"},
            justification = "Cannot break API"
        )
        //31=All:拥有全部权限
        //ANYONE_ID_UNSAFE:world方式授权给anyone
        ArrayList<ACL> OPEN_ACL_UNSAFE = new ArrayList(Collections.singletonList(new ACL(31, ANYONE_ID_UNSAFE)));
        @SuppressFBWarnings(
            value = {"MS_MUTABLE_COLLECTION"},
            justification = "Cannot break API"
        )
        //31=All:拥有全部权限
        //AUTH_IDS:auth方式授权给特定用户
        ArrayList<ACL> CREATOR_ALL_ACL = new ArrayList(Collections.singletonList(new ACL(31, AUTH_IDS)));
        @SuppressFBWarnings(
            value = {"MS_MUTABLE_COLLECTION"},
            justification = "Cannot break API"
        )
        //1=READ :拥有读权限
        //ANYONE_ID_UNSAFE:world方式授权给anyone
        ArrayList<ACL> READ_ACL_UNSAFE = new ArrayList(Collections.singletonList(new ACL(1, ANYONE_ID_UNSAFE)));
    }

    @Public
    public interface Perms {
        int READ = 1;
        int WRITE = 2;
        int CREATE = 4;
        int DELETE = 8;
        int ADMIN = 16;
        int ALL = 31;
    }
   ......
   ......
}
  1. create方法中第3个参数可以传ZooDefs类中3种参数:
  • ZooDefs.Ids.OPEN_ACL_UNSAFE:world方式授权每个人anyone都有cdrwa权限
  • ZooDefs.Ids.CREATOR_ALL_ACL:auth方式授权特定用户,有cdrwa权限
  • ZooDefs.Ids.READ_ACL_UNSAFE:world方式授权给anyone, r 权限
  1. 我们可以采用上面源码的方式自己创建权限给节点

(a)world方式授权给anyone

    @Test
    public void create2() throws Exception {
        List<ACL> acls = new ArrayList<>();
        Id id = new Id("world","anyone");
        // r 权限
        acls.add(new ACL(ZooDefs.Perms.READ,id));
        // w
        acls.add(new ACL(ZooDefs.Perms.WRITE,id));
        //其他权限,像上面一样加即可
        zooKeeper.create("/node/create2","hello2".getBytes(), acls , CreateMode.PERSISTENT);
    }

(b)ip方式授权

和上面一样,只需要修改创建Id的方式:Id id = new Id( "ip","192.168.60.130");

(c)digest方式授权

和上面一样,只需要修改创建Id的方式:Id id = new Id( "digest","gaolang:123456");// 用户名:密码
(d)auth方式授权特定用户

全部授权的话,可以直接用 ZooDefs.Ids.CREATOR_ALL_ACL

    @Test
    public void create3() throws Exception {
        //"gaolang:123456" :  用户名:密码
        zooKeeper.addAuthInfo("digest","gaolang:123456".getBytes());
        zooKeeper.create("/node/create3","hello3".getBytes(), ZooDefs.Ids.CREATOR_ALL_ACL , CreateMode.PERSISTENT);
    }

其他权限:

    @Test
    public void create4() throws Exception {

        zooKeeper.addAuthInfo("digest","gaolang:123456".getBytes());

        List<ACL> acls = new ArrayList<>();
        Id id = new Id("auth","gaolang");
        // r 权限
        acls.add(new ACL(ZooDefs.Perms.READ,id));
        // w
        acls.add(new ACL(ZooDefs.Perms.WRITE,id));
        //其他权限,像上面一样加即可

        zooKeeper.create("/node/create4","hello4".getBytes(), acls , CreateMode.PERSISTENT);
    }

临时节点、持久节点

临时节点还是持久节点的设置在create方法的第4个参数。我们上面创建节点的第4个参数都是CreateMode.PERSISTENT,也就是持久节点。

有4种参数:

  • 持久节点:CreateMode.PERSISTENT
  • 临时节点:CreateMode.EPHEMERAL
  • 持久化顺序节点:CreateMode.PERSISTENT_SEQUENTIAL
  • 临时顺序节点:CreateMode.EPHEMERAL_SEQUENTIAL

创建的临时节点我们是在zkCil.cmd上是查询不到的,因为我们程序是在连接-创建-关闭后,相当于我们一次会话结束,临时节点消失。

同步和异步方式

上面全部采用同步的方式:create方法执行完成后,且参数没有问题,客服端一定就会收到我们传来的信息,而异步执行完成后不代表客户端收到了。

异步方式:

    @Test
    public void create5() throws Exception{
        zooKeeper.create("/node/create5", "hello5".getBytes(), ZooDefs.Ids.CREATOR_ALL_ACL, CreateMode.PERSISTENT, 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(ctx);
            }
        },"Context");

        Thread.sleep(10000);
        System.out.println("结束");
    }

更新节点

更新方式

  1. 同步方式:
 // 同步
 setData(String path, byte[] data, int version)

  1. 异步方式:
  // 异步
  setData(String path, byte[] data, int version, StatCallback callBack, Object ctx)
  1. 参数含义:
参数解释
path节点路径
data数据
version数据的版本号, -1代表不使用版本号,乐观锁机制
callBack异步回调 AsyncCallback.StatCallback,和之前的回调方法参数不同,这个可以获取节点状态
ctx传递上下文参数
  1. 修改某个节点的值:
public class ZKUpdate {

    ZooKeeper zooKeeper;
    String IP = "127.0.0.1:2181";

    /*
    执行顺序:Before==》Test==》After
    before:连接zookeeper
    Test:更新节点
    after:关闭zookeeper连接
     */

    @Before
    public void before() throws Exception {
        //计数器对象
        CountDownLatch countDownLatch = new CountDownLatch(1);

        //new ZooKeeper(服务器的ip和端口,客户端与服务器之间的会话超时时间以毫秒为单位的,监视器对象)
        zooKeeper = new ZooKeeper(IP, 5000, new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                if (watchedEvent.getState() == Watcher.Event.KeeperState.SyncConnected) {
                    System.out.println("连接成功");
                    countDownLatch.countDown();
                }
            }
        });

        //主线程阻塞,等待连接对象创建成功
        countDownLatch.await();

    }

    @After
    public void after() throws Exception {
        zooKeeper.close();

    }



    @Test
    public void update() throws Exception{
        //第一个参数:节点的路径 
        //第二个参数:修改的数据
        //第三个参数:数据版本号   -1代表版本号不参与匹配

        zooKeeper.setData("/node/create","helloworld".getBytes(),-1);
    }
}

在这里插入图片描述

版本号更新

更新版本号在setDate方法的第3个参数:

(a)-1:代表版本号不参与匹配

(b)随机写一个数,比如 2,会版本号错误:org.apache.zookeeper.KeeperException$BadVersionException: KeeperErrorCode = BadVersion for /node/create

这是因为版本号不匹配的原因:
查看我们该节点的版本号:是 1 ,而我们匹配的版本号为2,自然报错
在这里插入图片描述

(c)版本号更新采用的是乐观锁机制,版本号匹配成功或者参数为-1不参与匹配的话,执行完后版本号加1

异步方式

异步方式修改:

    @Test
    public void update2() throws Exception {
        zooKeeper.setData("/node/create", "helloworld2".getBytes(), -1, 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());
            }
        },"Context");

        Thread.sleep(10000);
        System.out.println("结束");
    }

删除节点

删除方式

  1. 同步方式
 // 同步
 delete(String path, int version)

  1. 异步方式
  // 异步
  delete(String path, int version, AsyncCallback.VoidCallback callBack, Object ctx)
  1. 参数含义
参数解释
path节点路径
version版本
callBack数据的版本号, -1代表不使用版本号,乐观锁机制
ctx传递上下文参数
  1. 删除某个节点
public class ZKDelete {

    ZooKeeper zooKeeper;
    String IP = "127.0.0.1:2181";

    /*
    执行顺序:Before==》Test==》After
    before:连接zookeeper
    Test:删除节点
    after:关闭zookeeper连接
     */

    @Before
    public void before() throws Exception {
        //计数器对象
        CountDownLatch countDownLatch = new CountDownLatch(1);

        //new ZooKeeper(服务器的ip和端口,客户端与服务器之间的会话超时时间以毫秒为单位的,监视器对象)
        zooKeeper = new ZooKeeper(IP, 5000, new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                if (watchedEvent.getState() == Watcher.Event.KeeperState.SyncConnected) {
                    System.out.println("连接成功");
                    countDownLatch.countDown();
                }
            }
        });

        //主线程阻塞,等待连接对象创建成功
        countDownLatch.await();

    }

    @After
    public void after() throws Exception {
        zooKeeper.close();

    }

    @Test
    public void delete() throws Exception {
        //第一个参数:节点路径
        //第二个参数:版本信息  -1:不考虑版本信息
        zooKeeper.delete("/node/create",-1);
    }
}

在这里插入图片描述

异步方式

删除一个节点:

    @Test
    public void delete2() throws Exception {
        zooKeeper.delete("/node/create", -1, new AsyncCallback.VoidCallback() {
            @Override
            public void processResult(int rc, String path, Object ctx) {
                //0代表修改成功
                System.out.println(rc);
                //节点的路径
                System.out.println(path);
                //上下文参数对象
                System.out.println(ctx);
            }
        },"Context");
        
        Thread.sleep(10000);
        System.out.println("结束");
    }

查看节点

  1. 同步方式:
  // 同步
  getData(String path, boolean watch, Stat stat)
  getData(String path, Watcher watcher, Stat stat)

  1. 异步方式
  // 异步
  getData(String path, boolean watch, DataCallback callBack, Object ctx)
  getData(String path, Watcher watcher, DataCallback callBack, Object ctx)

3.参数含义

参数解释
path节点路径
boolean是否使用连接对象中注册的监听器
stat元数据
callBack异步回调接口,可以获得状态和数据
ctx传递上下文参数
  1. 代码实现
public class ZKGetData {

    ZooKeeper zooKeeper;
    String IP = "127.0.0.1:2181";

    /*
    执行顺序:Before==》Test==》After
    before:连接zookeeper
    Test:获取节点数据
    after:关闭zookeeper连接
     */

    @Before
    public void before() throws Exception {
        //计数器对象
        CountDownLatch countDownLatch = new CountDownLatch(1);

        //new ZooKeeper(服务器的ip和端口,客户端与服务器之间的会话超时时间以毫秒为单位的,监视器对象)
        zooKeeper = new ZooKeeper(IP, 5000, new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                if (watchedEvent.getState() == Watcher.Event.KeeperState.SyncConnected) {
                    System.out.println("连接成功");
                    countDownLatch.countDown();
                }
            }
        });

        //主线程阻塞,等待连接对象创建成功
        countDownLatch.await();

    }

    @After
    public void after() throws Exception {
        zooKeeper.close();

    }

    //同步方式:
    @Test
    public void getData() throws Exception {

        //第一个参数:节点路径
        //第三个参数:节点属性对象
        Stat stat = new Stat();
        byte[] data = zooKeeper.getData("/node/create3", false, stat);

        //打印数据:
        System.out.println(new String(data));
        //版本信息:
        System.out.println(stat.getVersion());

    }

    // 异步方式:
    @Test
    public void getData2() throws Exception {


        zooKeeper.getData("/node/create3", 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());
            }
        },"Context");

        Thread.sleep(10000);
        System.out.println("结束");
    }

}

查看子节点

  1. 同步方式
 // 同步
 getChildren(String path, boolean watch)
 getChildren(String path, Watcher watcher)
 getChildren(String path, boolean watch, Stat stat)    
 getChildren(String path, Watcher watcher, Stat stat)

  1. 异步方式
  // 异步
  getChildren(String path, boolean watch, ChildrenCallback callBack, Object ctx)    
  getChildren(String path, Watcher watcher, ChildrenCallback callBack, Object ctx)
  getChildren(String path, Watcher watcher, Children2Callback callBack, Object ctx)    
  getChildren(String path, boolean watch, Children2Callback callBack, Object ctx)
  1. 参数含义
参数解释
path节点路径
boolean是否使用连接对象中注册的监听器
callBack异步回调,可以获取节点列表
ctx传递上下文参数
  1. 代码实现
public class ZKGetChildren {

    ZooKeeper zooKeeper;
    String IP = "127.0.0.1:2181";

    /*
    执行顺序:Before==》Test==》After
    before:连接zookeeper
    Test:获取子节点
    after:关闭zookeeper连接
     */

    @Before
    public void before() throws Exception {
        //计数器对象
        CountDownLatch countDownLatch = new CountDownLatch(1);

        //new ZooKeeper(服务器的ip和端口,客户端与服务器之间的会话超时时间以毫秒为单位的,监视器对象)
        zooKeeper = new ZooKeeper(IP, 5000, new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                if (watchedEvent.getState() == Watcher.Event.KeeperState.SyncConnected) {
                    System.out.println("连接成功");
                    countDownLatch.countDown();
                }
            }
        });

        //主线程阻塞,等待连接对象创建成功
        countDownLatch.await();

    }

    @After
    public void after() throws Exception {
        zooKeeper.close();

    }


    //获取子节点

    //同步方式
    @Test
    public void get() throws Exception {
        //获取“/node”节点下的子节点
        List<String> children = zooKeeper.getChildren("/node", false);
        for (String child : children) {
            System.out.println(child);
        }
    }

    //异步方式
    @Test
    public void get2() throws Exception {
        zooKeeper.getChildren("/node", 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 child : children) {
                    System.out.println(child);
                }
            }
        }, "Context");
        
        Thread.sleep(10000);
        System.out.println("结束");
    }
}

检查节点是否存在

  1. 同步方式:
  // 同步
  exists(String path, boolean watch)
  exists(String path, Watcher watcher)
  
  1. 异步方式:
// 异步
  exists(String path, boolean watch, StatCallback cb, Object ctx)
  exists(String path, Watcher watcher, StatCallback cb, Object ctx)
  1. 参数解释
参数解释
path节点路径
boolean是否使用连接对象中注册的监听器
callBack异步回调,可以获取节点列表
ctx传递上下文参数
  1. 代码实现
public class ZKExistence {

    ZooKeeper zooKeeper;
    String IP = "127.0.0.1:2181";

    /*
    执行顺序:Before==》Test==》After
    before:连接zookeeper
    Test:更新节点
    after:关闭zookeeper连接
     */

    @Before
    public void before() throws Exception {
        //计数器对象
        CountDownLatch countDownLatch = new CountDownLatch(1);

        //new ZooKeeper(服务器的ip和端口,客户端与服务器之间的会话超时时间以毫秒为单位的,监视器对象)
        zooKeeper = new ZooKeeper(IP, 5000, new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                if (watchedEvent.getState() == Watcher.Event.KeeperState.SyncConnected) {
                    System.out.println("连接成功");
                    countDownLatch.countDown();
                }
            }
        });

        //主线程阻塞,等待连接对象创建成功
        countDownLatch.await();

    }

    @After
    public void after() throws Exception {
        zooKeeper.close();

    }


    //检查节点是否存在

    //同步方式:
    @Test
    public void existence() throws Exception {

        Stat stat = zooKeeper.exists("/node", false);

        if (stat == null){
            System.out.println("/node节点不存在");
        }else {
            System.out.println("/node节点存在,版本号为:"+stat.getVersion());
        }

    }

    //异步方式
    @Test
    public void existence2() throws Exception {
        zooKeeper.exists("/node", 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);
                //判断节点是否存在
                if (stat == null){
                    System.out.println("/node节点不存在");
                }else {
                    System.out.println("/node节点存在,版本号为:"+stat.getVersion());
                }
            }
        },"Context");

        Thread.sleep(10000);
        System.out.println("结束");
    }



}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值