zookeeper

Znode有四种形式的目录节点(默认是persistent )

(1)持久化节点(PERSISTENT)

默认 create /node1 aaa

客户端与zookeeper断开连接后,该节点依旧存在  

(2)持久化顺序节点(PERSISTENT_SEQUENTIAL)

创建zookeeper时会在路径上加上序号作为后缀,适合用于分布式锁、分布式选举等场所,创建时添加 -s 参数

create -s /node1 得到的是/node1_0000001 再次执行得到/node1_0000002

客户端与zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号 

(3)临时节点(EPHEMERAL)

不可再拥有子节点,跟连接会话绑定

客户端与zookeeper断开连接后,该节点有zk服务端自动删除,适用于心跳、服务发现等场景,创建时添加 -e 参数

(4)临时顺序节点(EPHEMERAL_SEQUENTIAL)

不可再拥有子节点,与持久化顺序节点类似,不同之处在于EPHEMERAL_SEQUENTIAL是临时的,会在回话断开后删除,创建时添加 -e -s 参数

 

 zookeeper选举机制

  第一次启动按照启动顺序以及MyId的值进行选举,满足:启动数量过半、启动早、MyId大 为leader

  非第一次选举

  1.判断当前剩余主机是否过半

  2.比较剩余主机数据,哪个最新,数据最新的直接当leader  参数:mZxid 数据新旧 值越大数据越新

  3.如果新旧程度一样,则比较MyId,谁最大谁就当leader

JavaAPI

建立连接:

 /**
     * 建立连接
     */
    @Before
    public void testConnect() {

        /*
         *
         * @param connectString       连接字符串。zk server 地址和端口 "192.168.149.135:2181,192.168.149.136:2181"
         * @param sessionTimeoutMs    会话超时时间 单位ms
         * @param connectionTimeoutMs 连接超时时间 单位ms
         * @param retryPolicy         重试策略
         */
       /* //重试策略
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(3000,10);
        //1.第一种方式
        CuratorFramework client = CuratorFrameworkFactory.newClient("192.168.149.135:2181",
                60 * 1000, 15 * 1000, retryPolicy);*/
        //重试策略
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(3000, 10);
        //2.第二种方式
        //CuratorFrameworkFactory.builder();
        client = CuratorFrameworkFactory.builder()
                .connectString("192.168.200.130:2181")
                .sessionTimeoutMs(60 * 1000)
                .connectionTimeoutMs(15 * 1000)
                .retryPolicy(retryPolicy)
                .namespace("mulumingchen")
                .build();

        //开启连接
        client.start();

    }

 

创建节点:create 持久 临时 顺序 数据;data为byte字节数组

1.基本创建:create().forPath("/demo") 在zookeeper根节点下创建demo

2.创建节点,带有数据:create().forPath("",data)

3.设置节点的类型:create().withMode().forPath("",data);withMode(CreateMode.上面四种节点类型值)

4.创建多级节点 /demo/d1:create().creatingParentsIfNeeded().forPath("/demo/d1",data);demo目录不存在时使用creatingParentsIfNeeded;临时性节点没有子节点

  @Test
    public void testCreate() throws Exception {
        //2. 创建节点 带有数据
        //如果创建节点,没有指定数据,则默认将当前客户端的ip作为数据存储
        String path = client.create().forPath("/app2", "hehe".getBytes());
        System.out.println(path);
    }

    @Test
    public void testCreate2() throws Exception {
        //1. 基本创建
        //如果创建节点,没有指定数据,则默认将当前客户端的ip作为数据存储
        String path = client.create().forPath("/app1");
        System.out.println(path);
    }

  /*
    节点类型:
    持久化节点:PERSISTENT
    持久化顺序节点:PERSISTENT_SEQUENTIAL
    临时化节点:EPHEMERAL
    临时化顺序节点:EPHEMERAL_SEQUENTIAL
  */
@Test
public void testCreate3() throws Exception { //3. 设置节点的类型 //默认类型:持久化 String path = client.create().withMode(CreateMode.EPHEMERAL).forPath("/app3"); System.out.println(path); } @Test public void testCreate4() throws Exception { //4. 创建多级节点 /app1/p1 //creatingParentsIfNeeded():如果父节点不存在,则创建父节点 String path = client.create().creatingParentsIfNeeded().forPath("/app4/p1"); System.out.println(path); }

查询节点:
1. 查询数据:get: getData().forPath()
2. 查询子节点: ls: getChildren().forPath()
3. 查询节点状态信息:ls -s:getData().storingStatIn(状态对象 Stat).forPath()

  @Test
    public void testGet1() throws Exception {
        //1. 查询数据:get
        byte[] data = client.getData().forPath("/app1");
        System.out.println(new String(data));
    }

    @Test
    public void testGet2() throws Exception {
        // 2. 查询子节点: ls
        List<String> path = client.getChildren().forPath("/");
        System.out.println(path);
    }

    @Test
    public void testGet3() throws Exception {

        Stat status = new Stat();
        System.out.println(status);
        //3. 查询节点状态信息:ls -s
        client.getData().storingStatIn(status).forPath("/app1");
        System.out.println(status);

    }

修改数据
1. 基本修改数据:setData().forPath()
2. 根据版本修改: setData().withVersion().forPath()
   version 是通过查询出来的。目的就是为了让其他客户端或者线程不干扰我。

   @Test
    public void testSet() throws Exception {
        client.setData().forPath("/app1", "itcast".getBytes());
    }


    @Test
    public void testSetForVersion() throws Exception {

        Stat status = new Stat();
        //3. 查询节点状态信息:ls -s
        client.getData().storingStatIn(status).forPath("/app1");


        int version = status.getVersion();//查询出来的 3
        System.out.println(version);
        client.setData().withVersion(version).forPath("/app1", "hehe".getBytes());
    }


删除节点: delete deleteall
1. 删除单个节点:delete().forPath("/app1");
2. 删除带有子节点的节点:delete().deletingChildrenIfNeeded().forPath("/app1");
3. 必须成功的删除:为了防止网络抖动。本质就是重试。 client.delete().guaranteed().forPath("/app2");
4. 回调:inBackground

   @Test
    public void testDelete() throws Exception {
        // 1. 删除单个节点
        client.delete().forPath("/app1");
    }

    @Test
    public void testDelete2() throws Exception {
        //2. 删除带有子节点的节点
        client.delete().deletingChildrenIfNeeded().forPath("/app4");
    }
    @Test
    public void testDelete3() throws Exception {
        //3. 必须成功的删除
        client.delete().guaranteed().forPath("/app2");
    }

    @Test
    public void testDelete4() throws Exception {
        //4. 回调
        client.delete().guaranteed().inBackground(new BackgroundCallback(){

            @Override
            public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
                System.out.println("我被删除了~");
                System.out.println(event);
            }
        }).forPath("/app1");
    }

 

posted @ 2022-04-16 21:29  景、  阅读(36)  评论(0编辑  收藏  举报