zookeeper——客户端Curator 的简单操作

目录

 

curator简介

1.curator连接zookeeper

2.创建节点

2.1简单创建

2.2 自定义权限

2.3递归创建

2.4异步创建

3.修改节点

3.1 同步修改

3.2 异步修改

4.删除节点

4.1同步删除

4.2异步删除

5.查看节点数据

5.1同步方式

5.2异步方式

6.查看子节点

6.1同步方式

6.2 异步方式

7.是否存在

7.1同步方式

7.2异步方式

8.监视器

8.1监视当前节点

8.2 监听子节点

9.事务

10.分布式锁

 


curator简介

curator是Netfilx公司开源的一个zookeeper客户端,后捐献给apache,curator框架在zookeeper原生API接口上进行了包装,解决了很多zookeeper客户端非常底层的细节开发。提供zookeeper各种应用场景(比如:分布式锁服务、集群领导选举、共享计数器、缓存机制、分布式队列等)的抽象封装,实现了Fluent风格的API接口,是最好用,最流行的zookeeper的客户端。

 

导入依赖:

<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-recipes -->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>4.2.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.curator/curator-framework -->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>4.2.0</version>
        </dependency>

1.curator连接zookeeper

package com.cjian.curator;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.RetryOneTime;


public class CuratorConnection {
    public static void main(String[] args) {
        /**
         * 重连策略
         * new RetryOneTime(3000)  三秒后重连一次,只重连一次
         * new RetryNTimes(3, 3000); 每三秒重连一次,重连三次
         * new RetryUntilElapsed(10000, 3000); 每三秒重连一次,总等待时间超过10秒后停止重连
         * new ExponentialBackoffRetry(1000, 3);随着重连次数的增加,重连的时间增加  baseSleepTimeMs*Math.max(1,random.nextInt(1<<retryCount+1))
         *
         */
        CuratorFramework client = CuratorFrameworkFactory.builder()
            //IP端口号
            .connectString("127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183")
            //会话超时时间
            .sessionTimeoutMs(5000)
            //重连机制  策略
            .retryPolicy(new RetryOneTime(3000))
            //命名空间  父节点
            .namespace("create")
            //构建连接对象
            .build();
        //打开连接
        client.start();
        System.out.println(client.isStarted());
        //关闭连接
        client.close();
    }

}

2.创建节点

2.1简单创建

 @Test
    public void create1() throws Exception {
        client.create()
            .withMode(CreateMode.PERSISTENT)
            .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
            .forPath("/node1", "node1".getBytes());
        System.out.println("创建结束");
    }
[zk: 127.0.0.1:2182(CONNECTED) 3] ls /
[zookeeper]
[zk: 127.0.0.1:2182(CONNECTED) 4] ls /
[create, zookeeper]
[zk: 127.0.0.1:2182(CONNECTED) 5] get /create/node1
node1
cZxid = 0x300000025
ctime = Tue Feb 02 09:21:13 CST 2021
mZxid = 0x300000025
mtime = Tue Feb 02 09:21:13 CST 2021
pZxid = 0x300000025
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0

2.2 自定义权限

@Test
    public void create2() throws Exception {
        //自定义权限列表
        ArrayList<ACL> acls = new ArrayList<>();
        Id id = new Id("ip", "127.0.0.1");
        acls.add(new ACL(ZooDefs.Perms.ALL, id));
        client.create()
            .withMode(CreateMode.PERSISTENT)
            .withACL(acls)
            .forPath("/node2", "node2".getBytes());
        System.out.println("创建结束");
    }
[zk: 127.0.0.1:2182(CONNECTED) 7] getAcl /create/node2
'ip,'127.0.0.1
: cdrwa

2.3递归创建

 @Test
    public void create3() throws Exception {
        //递归创建节点树
        client.create()
            .creatingParentsIfNeeded()//支持递归创建节点
            .withMode(CreateMode.PERSISTENT)
            .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
            .forPath("/node3/node31", "node31".getBytes());
    }

2.4异步创建

@Test
    public void create4() throws Exception {
        //异步方式创建节点
        client.create()
            .creatingParentsIfNeeded()//支持递归创建节点
            .withMode(CreateMode.PERSISTENT)
            .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
            .inBackground(new BackgroundCallback() {
                @Override
                public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent)
                    throws Exception {
                    //节点路径
                    System.out.println(curatorEvent.getPath());
                    //事件类型
                    System.out.println(curatorEvent.getType());
                }
            })
            .forPath("/node4", "node4".getBytes());
        Thread.sleep(5000);
        System.out.println("创建结束");
    }
/node4
CREATE
创建结束

3.修改节点

3.1 同步修改

@Test
    public void set1() throws Exception {
        client.setData()
            .forPath("/node1", "node11".getBytes());
    }
    @Test
    public void set2() throws Exception {
        client.setData()
            //指定版本号
            .withVersion(-1)
            .forPath("/node1", "node22".getBytes());
    }

3.2 异步修改

 @Test
    public void set3() throws Exception {
        //异步方式
        client.setData()
            //指定版本号
            .withVersion(-1)
            .inBackground(new BackgroundCallback() {
                @Override
                public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent)
                    throws Exception {
                    //节点路径
                    System.out.println(curatorEvent.getPath());
                    //事件类型
                    System.out.println(curatorEvent.getType());
                }
            })
            .forPath("/node1", "node33".getBytes());
        Thread.sleep(5000);
        System.out.println("修改结束");
    }
/node1
SET_DATA
修改结束

4.删除节点

4.1同步删除

  @Test
    public void delete1() throws Exception {
        client.delete().forPath("/node1");
    }
    @Test
    public void delete2() throws Exception {
        client.delete()
            //版本号
            .withVersion(-1)
            .forPath("/node1");
    }

    @Test
    public void delete3() throws Exception {
        client.delete()
            //删除包含子节点的节点
            .deletingChildrenIfNeeded()
            .forPath("/node1");
    }

4.2异步删除

 @Test
    public void delete4() throws Exception {
        client.delete()
            //删除包含子节点的节点
            .deletingChildrenIfNeeded()
            .withVersion(-1)
            .inBackground(new BackgroundCallback() {
                @Override
                public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent)
                    throws Exception {
                    //节点路径
                    System.out.println(curatorEvent.getPath());
                    //事件类型
                    System.out.println(curatorEvent.getType());
                }
            })
            .forPath("/node1");
        Thread.sleep(5000);
        System.out.println("删除结束");
    }
/node1
DELETE
删除结束

5.查看节点数据

5.1同步方式

  @Test
    public void getData1() throws Exception {
        //读取节点数据
        byte[] node2s = client.getData().forPath("/node2");
        System.out.println(new String(node2s));
    }

    @Test
    public void getData2() throws Exception {
        Stat stat = new Stat();
        //读取数据时读取节点的属性
        byte[] node2s = client.getData()
            .storingStatIn(stat).forPath("/node2");
        System.out.println(new String(node2s));
        System.out.println(stat.getVersion());

    }

5.2异步方式

@Test
    public void getData3() throws Exception {
        Stat stat = new Stat();
        //读取数据时读取节点的属性
        byte[] node2s = client.getData()
            .inBackground(new BackgroundCallback() {
                @Override
                public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent)
                    throws Exception {
                    //节点路径
                    System.out.println(curatorEvent.getPath());
                    //事件类型
                    System.out.println(curatorEvent.getType());
                    //数据
                    System.out.println(new String(curatorEvent.getData()));
                }
            }).forPath("/node2");
        Thread.sleep(5000);
    }
/node2
GET_DATA
node2

6.查看子节点

6.1同步方式

 @Test
    public void getChild1() throws Exception {
        List<String> list = client.getChildren().forPath("/node1");
        for (String s : list) {
            System.out.println(s);
        }
    }
node11

6.2 异步方式

@Test
    public void getChild2() throws Exception {
        client.getChildren()
            .inBackground(new BackgroundCallback() {
                @Override
                public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent)
                    throws Exception {
                    //节点路径
                    System.out.println(curatorEvent.getPath());
                    //事件类型
                    System.out.println(curatorEvent.getType());
                    List<String> list = curatorEvent.getChildren();
                    for (String s : list) {
                        System.out.println(s);
                    }
                }
            }).forPath("/node1");
        Thread.sleep(5000);
    }
/node1
CHILDREN
node11

7.是否存在

7.1同步方式

@Test
    public void exists1() throws Exception {
        Stat stat = client.checkExists().forPath("/node1");
        System.out.println(stat.getVersion());
    }

如果不存在,则stat为null

7.2异步方式

@Test
    public void exists2() throws Exception {
        client.checkExists()
            .inBackground(new BackgroundCallback() {
                @Override
                public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent)
                    throws Exception {
                    //节点路径
                    System.out.println(curatorEvent.getPath());
                    //事件类型
                    System.out.println(curatorEvent.getType());

                    System.out.println(curatorEvent.getStat().getVersion());
                }
            }).forPath("/node1");
    }
/node1
EXISTS
0

8.监视器

curator提供了两种watcher来监听节点的变化

  • NodeCache :之间听某一个特定的节点,监听节点的新增和修改
  • PathChildrenCache:监听一个znode的子节点,当一个子节点增加、更新、删除时PathChildrenCache会改变它的状态,会包含最新的子节点,子节点的数据和状态

监视器可重复使用

8.1监视当前节点

@Test
    public void watcher1() throws Exception {
        //监视某个节点的数据变化
        NodeCache nodeCache = new NodeCache(client, "/watcher");
        //开启监视器对象
        nodeCache.start();
        nodeCache.getListenable().addListener(new NodeCacheListener() {
            @Override
            public void nodeChanged() throws Exception {
                System.out.println(nodeCache.getCurrentData().getPath());
                System.out.println(new String(nodeCache.getCurrentData().getData()));
            }
        });
        Thread.sleep(60000);
        //关闭监视器对象
        nodeCache.close();
    }

首先该节点是没有的,当我们在命令窗口执行:create /create/watcher "111"  后,控制台输出:

/watcher
111

当我们在控制台再次执行:set /create/watcher "222" 后,控制台输出:

/watcher
222

8.2 监听子节点

@Test
    public void watcher2() throws Exception {
        //监视某个子节点的数据变化
        //第三个参数为事件中是否可以获取节点的数据
        PathChildrenCache pathChildrenCache = new PathChildrenCache(client, "/watcher",true);
        //开启监视器对象
        pathChildrenCache.start();
        pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() {
            @Override
            public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent)
                throws Exception {
                System.out.println(pathChildrenCacheEvent.getType());
                System.out.println(pathChildrenCacheEvent.getData().getPath());
                System.out.println(new String(pathChildrenCacheEvent.getData().getData()));
            }
        });
        Thread.sleep(60000);
        //关闭监视器对象
        pathChildrenCache.close();
    }

首先该节点是没有的,当我们在命令窗口执行:create /create/watcher/watcher1 "11"  后,控制台输出:

CHILD_ADDED
/watcher/watcher1
11

当我们在控制台再次执行: set /create/watcher/watcher1 "123" 后,控制台输出:

CHILD_UPDATED
/watcher/watcher1
123

当我们在控制台再次执行: delete /create/watcher/watcher1 后,控制台输出:

CHILD_REMOVED
/watcher/watcher1
123

9.事务

//事务
    @Test
    public void tra1() throws Exception {
        //开启事务
        client.inTransaction().create().forPath("/test1","test1".getBytes())
            .and()
            .setData().forPath("/notExistsNode","not exists".getBytes())
            .and()
            //提交事务
            .commit();
    }

10.分布式锁

package com.cjian.curator;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessLock;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;

public class CuratorLock {
    private static CuratorFramework client;


    public static void main(String[] args) throws InterruptedException {
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
        client = CuratorFrameworkFactory.builder()
            .connectString("127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183")
            .sessionTimeoutMs(5000)
            .retryPolicy(retryPolicy)
            //可选项
            .namespace("lock")
            .build();
        client.start();

          //排他锁
        InterProcessLock interProcessLock = new InterProcessMutex(client, "/lock1");
        //读写锁
        //InterProcessReadWriteLock interProcessReadWriteLock = new InterProcessReadWriteLock(client, "/lock1");

        Order order = new Order(0,interProcessLock);
        for (int i = 0; i < 5; i++) {
            new Thread(order).start();
        }
        Thread.sleep(10000);
        System.out.println(order.getNum());

    }
}
class  Order implements Runnable{
    private int num;
    private InterProcessLock interProcessLock;

    public Order(int num, InterProcessLock interProcessLock) {
        this.num = num;
        this.interProcessLock = interProcessLock;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try {
                interProcessLock.acquire();
                num++;
                interProcessLock.release();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }
}

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值