ZooKeeper分布式协调服务(节点分类、事件监听、java集成)

  • 阿里云国际版折扣https://www.yundadi.com

  • 阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

    文章目录

    前言

    ZooKeeper是一个分布式的开放源码的分布式应用程序协调服务是GoogleChubby一个开源的实现是HadoopHbase的重要组件。它是一个为分布式应用提供一致性服务的软件提供的功能包括配置维护、域名服务、分布式同步、组服务等。

    安装启动

    安装把zk安装包上传到/opt目录下并切换到/opt目录下执行以下指令

    # 解压
    tar -zxvf zookeeper-3.7.0-bin.tar.gz
    # 重命名
    mv apache-zookeeper-3.7.0-bin/ zookeeper
    # 打开zookeeper根目录
    cd /opt/zookeeper
    # 创建一个数据目录备用
    mkdir data
    # 打开zk的配置目录
    cd /opt/zookeeper/conf
    # copy配置文件zk启动时会加载zoo.cfg文件
    cp zoo_sample.cfg zoo.cfg
    # 编辑配置文件
    vim zoo.cfg
    # 修改dataDir参数为之前创建的数据目录/opt/zookeeper/data
    # 切换到bin目录
    cd /opt/zookeeper/bin
    # 启动 
    ./zkServer.sh start
    ./zkServer.sh status # 查看启动状态
    ./zkServer.sh stop # 停止
    ./zkServer.sh restart # 重启
    ./zkCli.sh # 查看zk客户端
    

    如下说明启动成功

    在这里插入图片描述

    相关概念

    Zookeeper提供一个多层级的节点命名空间节点称为znode每个节点都用一个以斜杠/分隔的路径表示而且每个节点都有父节点根节点除外非常类似于文件系统。并且每个节点都是唯一的。

    znode节点有四种类型

    • PERSISTENT永久节点。客户端与zookeeper断开连接后该节点依旧存在
    • EPHEMERAL临时节点。客户端与zookeeper断开连接后该节点被删除
    • PERSISTENT_SEQUENTIAL永久节点、序列化。客户端与zookeeper断开连接后该节点依旧存在只是Zookeeper给该节点名称进行顺序编号
    • EPHEMERAL_SEQUENTIAL临时节点、序列化。客户端与zookeeper断开连接后该节点被删除只是Zookeeper给该节点名称进行顺序编号

    操作节点

    创建这四种节点

    [zk: localhost:2181(CONNECTED) 0] create /aa test  # 创建持久化节点
    Created /aa
    [zk: localhost:2181(CONNECTED) 1] create -s /bb test  # 创建持久序列化节点
    Created /bb0000000001
    [zk: localhost:2181(CONNECTED) 2] create -e /cc test  # 创建临时节点
    Created /cc
    [zk: localhost:2181(CONNECTED) 3] create -e -s /dd test  # 创建临时序列化节点
    Created /dd0000000003
    [zk: localhost:2181(CONNECTED) 4] ls /   # 查看某个节点下的子节点
    [aa, bb0000000001, cc, dd0000000003, zookeeper]
    [zk: localhost:2181(CONNECTED) 5] stat /  # 查看某个节点的状态
    cZxid = 0x0
    ctime = Thu Jan 01 08:00:00 CST 1970
    mZxid = 0x0
    mtime = Thu Jan 01 08:00:00 CST 1970
    pZxid = 0x5
    cversion = 3
    dataVersion = 0
    aclVersion = 0
    ephemeralOwner = 0x0
    dataLength = 0
    numChildren = 5
    [zk: localhost:2181(CONNECTED) 6] get /aa  # 查看某个节点的内容
    test
    [zk: localhost:2181(CONNECTED) 11] delete /aa  # 删除某个节点
    [zk: localhost:2181(CONNECTED) 7] ls /  # 再次查看
    [bb0000000001, cc, dd0000000003, zookeeper]
    

    事件监听

    在读取数据时我们可以同时对节点设置事件监听当节点数据或结构变化时zookeeper会通知客户端。当前zookeeper针对节点的监听有如下四种事件

    1. 节点创建stat -w /xx

      当/xx节点创建时NodeCreated

    2. 节点删除stat -w /xx

      当/xx节点删除时NodeDeleted

    3. 节点数据修改get -w /xx

      当/xx节点数据发生变化时NodeDataChanged

    4. 子节点变更ls -w /xx

      当/xx节点的子节点创建或者删除时NodeChildChanged

    java客户端

    ZooKeeperjava客户端有原生客户端、ZkClientCurator框架类似于redisson有很多功能性封装。

    1. 引入依赖
    <dependency>
        <groupId>org.apache.zookeeper</groupId>
        <artifactId>zookeeper</artifactId>
        <version>3.7.0</version>
    </dependency>
    
    1. 常用api及其方法
    public class ZkTest {
    
        public static void main(String[] args) throws KeeperException, InterruptedException {
    
            // 获取zookeeper链接
            CountDownLatch countDownLatch = new CountDownLatch(1);
            ZooKeeper zooKeeper = null;
            try {
                zooKeeper = new ZooKeeper("172.16.116.100:2181", 30000, new Watcher() {
                    @Override
                    public void process(WatchedEvent event) {
                        if (Event.KeeperState.SyncConnected.equals(event.getState()) 
                                && Event.EventType.None.equals(event.getType())) {
                            System.out.println("获取链接成功。。。。。。" + event);
                            countDownLatch.countDown();
                        }
                    }
                });
    
                countDownLatch.await();
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            // 创建一个节点1-节点路径 2-节点内容 3-节点的访问权限 4-节点类型
            // OPEN_ACL_UNSAFE任何人可以操作该节点
            // CREATOR_ALL_ACL创建者拥有所有访问权限
            // READ_ACL_UNSAFE: 任何人都可以读取该节点
            // zooKeeper.create("/zktest/aa", "haha~~".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            zooKeeper.create("/test", "haha~~".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
            // zooKeeper.create("/zktest/cc", "haha~~".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
            // zooKeeper.create("/zktest/dd", "haha~~".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
            // zooKeeper.create("/zktest/dd", "haha~~".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
            // zooKeeper.create("/zktest/dd", "haha~~".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
    
            // 判断节点是否存在
            Stat stat = zooKeeper.exists("/test", true);
            if (stat != null){
                System.out.println("当前节点存在" + stat.getVersion());
            } else {
                System.out.println("当前节点不存在");
            }
    
            // 判断节点是否存在同时添加监听
            zooKeeper.exists("/test", event -> {
            });
    
            // 获取一个节点的数据
            byte[] data = zooKeeper.getData("/zktest/ss0000000001", false, null);
            System.out.println(new String(data));
    
            // 查询一个节点的所有子节点
            List<String> children = zooKeeper.getChildren("/test", false);
            System.out.println(children);
    
            // 更新
            zooKeeper.setData("/test", "wawa...".getBytes(), stat.getVersion());
    
            // 删除一个节点
            //zooKeeper.delete("/test", -1);
    
            if (zooKeeper != null){
                zooKeeper.close();
            }
        }
    }
    
  • 阿里云国际版折扣https://www.yundadi.com

  • 阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
    标签: Java