使用Zookeeper API 对Zookeeper的增删查改操作

简介:本篇博客主要是使用Zookeeper的API对Zookeeper的增删查改,但是在递归实现节点的数据变化监控时,这里始终没有写好,希望有大神帮我指点迷津,感谢!

package com.lqs.api.zookeeper;

import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.util.List;

/**
 * @author qingSong liu
 * @version 1.0
 * @time 2021/12/18 20:20
 */

public class ZookeeperDemo {

    private String connectString;
    private ZooKeeper zooKeeper;
    private int sessionTimeout;

    /**
     * 获取客户端对象
     */
    @Before
    public void init() throws IOException {
        connectString = "bdc112:2181,bdc113:2181,bdc114:2181";
        sessionTimeout = 3000;

        zooKeeper = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
//                System.out.println(watchedEvent);
            }
        });
    }

    /**
     * 关闭客户端对象
     */
    @After
    public void close() throws InterruptedException {
        zooKeeper.close();
    }

    /**
     * 获取子节点列表,且不监听
     */
    @Test
    public void ls() throws InterruptedException, KeeperException {
        //通过客户端对象对Zookeeper进行各种操作
        List<String> children = zooKeeper.getChildren("/", false);
        System.out.println(children);
    }

    /**
     * 获取子节点列表并监听
     */
    @Test
    public void lsAndWatch() throws InterruptedException, KeeperException {

        final boolean[] flag = {false};

        List<String> children = zooKeeper.getChildren("/test", new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                System.out.println(watchedEvent);
                flag[0] = true;
                System.exit(flag[0] ? 0 : 1);
                try {
                    lsAndWatch();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (KeeperException e) {
                    e.printStackTrace();
                }
            }
        });

        System.out.println(children);
        //这里设置睡眠是需要监听,所以当前的线程不能结束
        Thread.sleep(Long.MAX_VALUE);

    }

    /**
     * 创建子节点
     */
    @Test
    public void create() throws InterruptedException, KeeperException {

        //参数解读 1节点路径  2节点存储的数据
        //3节点的权限(使用Ids选个OPEN即可) 4节点类型 短暂 持久 短暂带序号 持久带序号

        /**
         * CONTAINER 序列化节点
         * EPHEMERAL 短暂的
         * EPHEMERAL_SEQUENTIAL 临时序列
         * PERSISTENT 执着的,持久
         * PERSISTENT_SEQUENTIAL 持久化序列
         * PERSISTENT_SEQUENTIAL_WITH_TTL 具有 TTL 的持久序列
         * PERSISTENT_WITH_TTL 使用 TTL 持久化
         */

        //创建持久序列
        String path = zooKeeper.create("/test12", "test11".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.CONTAINER);

        //创建临时节点
//        String path = zooKeeper.create("/testLin", "test22".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);

        //创建临时序列
//        String path = zooKeeper.create("/test", "test12".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);

        //一定要注意,创建临时节点的话,需要线程阻塞,否则看不到效果
        //Thread.sleep(10000);


        //创建持久化序列
//        String path = zooKeeper.create("/test", "test".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);

        //创建持久化节点
//        String path = zooKeeper.create("/test/test11", "test".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);


    }

    /**
     * 判断Node是否存在
     */
    @Test
    public void exist() throws InterruptedException, KeeperException {

        Stat stat = zooKeeper.exists("/test", false);
        System.out.println(stat != null ? "文件存在..." : "文件不存在...");

    }

    /**
     * 获取子节点存储的数据,但不监听
     */
    @Test
    public void get() throws InterruptedException, KeeperException {

        //判断节点是否存在,在Zookeeper中
        Stat stat = zooKeeper.exists("/test", false);

        if (stat == null) {
            System.out.println("当前节点不存在...");
        } else {
            byte[] data = zooKeeper.getData("/test", false, stat);
            System.out.println(new String(data));
        }

    }

    /**
     * 获取子节点存储的数据,并监听
     */
    @Test
    public void getAndWatch() throws InterruptedException, KeeperException {

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

        if (stat == null) {
            System.out.println("当前节点不存在...");
            return;
        }

        final boolean[] flagOut = {true};

        //这里监听的是我们获取子节点的数据有没有发生变化
        byte[] data = zooKeeper.getData("/test12", new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                System.out.println(watchedEvent);
                flagOut[0] = true;
            }
        }, stat);


        if (flagOut[0]) {
            System.out.println(new String(data));
        }

        /**
         * 递归,可以实时监听节点的数据有没有发生变化
         * 但是我这里写的不够完美,会出现一直调用的情况,当你的节点数据发生变化时,他就会打印出变化情况(但是
         * 打印多个,具体多少打印多少次,就看你你递归多少次了
         */
        while (true) {
            //睡眠时间为1秒,即1秒中调用一次
            Thread.sleep(1000);
//            flagOut[0] =false;
            if (flagOut[0]) {
                getAndWatch();
            }

        }


    }

    /**
     * 设置节点的值
     */
    @Test
    public void set() throws InterruptedException, KeeperException {

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

        if (stat == null) {
            System.out.println("当前节点不存在...");
            return;
        }

        Stat result = zooKeeper.setData("/test", "test".getBytes(), stat.getVersion());

        System.out.println(result != null ? "设置节点值成功..." : "设置节点值失败...");
    }

    private Stat getStat(String path) throws InterruptedException, KeeperException {
        Stat stat = zooKeeper.exists(path, false);

        if (stat == null) {
            System.out.println("当前节点不存在...");
            exist();
        }

        return stat;
    }

    /**
     * 删除空节点
     */
    @Test
    public void rm() throws InterruptedException, KeeperException {

        Stat result = getStat("/test0000000006");

        zooKeeper.delete("/test0000000006", result.getVersion());
    }

    /**
     * 删除非空节点,递归实现
     */
    public void deleteAll(String path) throws InterruptedException, KeeperException {
        Stat stat = getStat(path);
        List<String> children = zooKeeper.getChildren(path, false);

        for (String child : children) {

            deleteAll(path + "/" + child);
        }

//        zooKeeper.delete(path,stat.getVersion());
        //这里的version即stat里面的得到的节点的dataversion - znode数据变化号。如果不知道是多少,则传入-1即可
        zooKeeper.delete(path, -1);
    }


    @Test
    public void deleteAllTest() throws InterruptedException, KeeperException {

        deleteAll("/test");

    }

    /**
     * 获取子节点的列表,并循环监听
     * 先封装一个方法,方便递归调用
     */
    public void lsAndWatch(String path) throws InterruptedException, KeeperException {

        List<String> children = zooKeeper.getChildren(path, new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                System.out.println(watchedEvent);
                try {
                    lsAndWatch(path);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (KeeperException e) {
                    e.printStackTrace();
                }
            }
        });

        System.out.println(children);

    }

    @Test
    public void testWatch() throws InterruptedException, KeeperException {
        lsAndWatch("/test");
        Thread.sleep(Long.MAX_VALUE);
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小雏菊的成长

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值