【zookeeper】Apache curator优点介绍

1. 简介

Apache Curator是一个比较完善的ZooKeeper客户端框架,通过封装的一套高级API 简化了ZooKeeper的操作。通过查看官方文档,可以发现Curator主要解决了三类问题:

  • 封装ZooKeeper client与ZooKeeper server之间的连接处理
  • 提供了一套Fluent风格的操作API
  • 提供ZooKeeper各种应用场景(recipe, 比如:分布式锁服务、集群领导- 选举、共享计数器、缓存机制、分布式队列等)的抽象封装

Curator主要从以下几个方面降低了zk使用的复杂性:

  • 重试机制:提供可插拔的重试机制, 它将给捕获所有可恢复的异常配置一个- 重试策略,并且内部也提供了几种标准的重试策略(比如指数补偿)

  • 连接状态监控: Curator初始化之后会一直对zk连接进行监听,一旦发现连接状态发生变化将会作出相应的处理

    比如自动重连

  • zk客户端实例管理:Curator会对zk客户端到server集群的连接进行管理,并在需要的时候重建zk实例,保证与zk集群连接的可靠性

  • 各种使用场景支持:Curator实现了zk支持的大部分使用场景(甚至包括zk自身不支持的场景),这些实现都遵循了zk的最佳实践,并考虑了各种极端情况

  • 支持反复注册Watcher

  • 创建持久化节点时候递归创建

2. 项目组件

2.1 版本

目前Curator有2.x.x和3.x.x两个系列的版本,支持不同版本的Zookeeper。其中Curator 2.x.x兼容Zookeeper的3.4.x和3.5.x。而Curator 3.x.x只兼容Zookeeper 3.5.x,并且提供了一些诸如动态重新配置、watch删除等新特性。

原文资料比较老,可以参见官网最新 《官网》

2.2 项目组件

在这里插入图片描述
原文资料比较老,可以参见官网最新 《官网》

2.3 Maven依赖

Curator的jar包已经发布到Maven中心,由以下几个artifact的组成。根据需要选择引入具体的artifact。但大多数情况下只用引入curator-recipes即可。

当然,curator-recipes依赖了curator-framework和curator-client,必须设置自动下载依赖,这样间接引入curator-framework和curator-client。

在这里插入图片描述
根据上面的描述,开发人员大多数情况下使用的都是curator-recipes的依赖,此依赖的maven配置如下:

<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-recipes</artifactId>
    <version>2.12.0</version>
</dependency>

3. 案例及功能说明

3.1 创建会话

Curator的创建会话方式与原生的API和ZkClient的创建方式区别很大。Curator创建客户端是通过CuratorFrameworkFactory工厂类来实现的。其中,此工厂类提供了三种创建客户端的方法。

前两种方法是通过newClient来实现,仅参数不同而已。

//构造方法1
public static CuratorFramework newClient(String connectString, RetryPolicy retryPolicy)
//构造方法2
public static CuratorFramework newClient(String connectString, int sessionTimeoutMs, int connectionTimeoutMs, RetryPolicy retryPolicy)

使用上面方法创建出一个CuratorFramework之后,需要再调用其start()方法完成会话创建。

构造方法1实例代码:

//构造方法1
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
CuratorFramework client = CuratorFrameworkFactory.newClient("127.0.0.1:2181",retryPolicy);
client.start();

构造方法2实例代码:

//构造方法2
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
CuratorFramework client = CuratorFrameworkFactory.newClient("127.0.0.1:2181",
                5000,1000,retryPolicy);
client.start();

其中参数RetryPolicy提供重试策略的接口,可以让用户实现自定义的重试策略。默认提供了以下实现,分别为ExponentialBackoffRetry、BoundedExponentialBackoffRetry、RetryForever、RetryNTimes、RetryOneTime、RetryUntilElapsed

进一步查看源代码可以得知,其实这两种方法内部实现一样,只是对外包装成不同的方法。它们的底层都是通过第三个方法builder来实现的。

构造方法3实例代码:

//构造方法3
RetryPolicy retryPolicy  = new ExponentialBackoffRetry(1000,3);
private static CuratorFramework Client = CuratorFrameworkFactory.builder()
            .connectString("hadoop1:2181,hadoop2:2181,hadoop3:2181")
            .sessionTimeoutMs(3000)
            .connectionTimeoutMs(5000)
            .retryPolicy(retryPolicy)
            .build();
client.start();

Curator提供了一套Fluent风格的操作API。这在很多脚本类语言里比较流行,构造方法3正是这种风格。

参数:

  • connectString:zk的server地址,多个server之间使用英文逗号分隔开
  • connectionTimeoutMs:连接超时时间,如上是30s,默认是15s
  • sessionTimeoutMs:会话超时时间,如上是50s,默认是60s
  • retryPolicy:失败重试策略
    • ExponentialBackoffRetry:构造器含有三个参数 ExponentialBackoffRetry(int baseSleepTimeMs, int maxRetries, int maxSleepMs)
      • baseSleepTimeMs:初始的sleep时间,用于计算之后的每次重试的sleep时间,
        计算公式:当前sleep时间=baseSleepTimeMs*Math.max(1, random.nextInt(1<<(retryCount+1)))
      • maxRetries:最大重试次数
      • maxSleepMs:最大sleep时间,如果上述的当前sleep计算出来比这个大,那么sleep用这个时间
    • 其他,查看org.apache.curator.RetryPolicy接口的实现类
  • start()会阻塞到会话创建成功为止。

3.1.1 重试策略

上面的例子中使用到了ExponentialBackoffRetry重试策略实现。此策略先给定一个初始化sleep时间baseSleepTimeMs,在此基础上结合重试次数,通过以下代码计算当前需要的sleep时间:

long sleepMs = baseSleepTimeMs * Math.max(1, random.nextInt(1 << (retryCount + 1)));
if ( sleepMs > maxSleepMs ){
            sleepMs = maxSleepMs;
 }

随着重试次数的增加,计算出的sleep时间也会越来越大。如果超过maxSleepMs则使用maxSleepMs的时间。其中maxRetries限制了最大的尝试次数。

3.1.2 创建节点

Curator创建节点的方法也是基于Fluent风格编码,原生API中的参数很多都转化为一层层的方法调用来进行设置。下面简单介绍一下常用的几个节点创建场景。
(1)创建一个初始内容为空的节点

client.create().forPath(path);

Curator默认创建的是持久节点,内容为空。

(2)创建一个包含内容的节点

client.create().forPath(path,"我是内容".getBytes());

Curator和ZkClient不同的是依旧采用Zookeeper原生API的风格,内容使用byte[]作为方法参数。

(3)创建临时节点,并递归创建父节点

client.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL).forPath(path);

此处Curator和ZkClient一样封装了递归创建父节点的方法。在递归创建父节点时,父节点为持久节点。

3.1.3 删除节点

删除节点的方法也是基于Fluent方式来进行操作,不同类型的操作调用新增不同的方法调用即可。

(1)删除一个子节点

client.delete().forPath(path);

(2)删除节点并递归删除其子节点

client.delete().deletingChildrenIfNeeded().forPath(path);

(3)指定版本进行删除

client.delete().withVersion(1).forPath(path);

如果此版本已经不存在,则删除异常,异常信息如下:

org.apache.zookeeper.KeeperException$BadVersionException: KeeperErrorCode = BadVersion for

(4)强制保证删除一个节点

client.delete().guaranteed().forPath(path);

只要客户端会话有效,那么Curator会在后台持续进行删除操作,直到节点删除成功。比如遇到一些网络异常的情况,此guaranteed的强制删除就会很有效果。

3.1.4 读取数据

读取节点数据内容API相当简单,Curator提供了传入一个Stat,使用节点当前的Stat替换到传入的Stat的方法,查询方法执行完成之后,Stat引用已经执行当前最新的节点Stat。

// 普通查询
client.getData().forPath(path);
// 包含状态查询
Stat stat = new Stat();
client.getData().storingStatIn(stat()).forPath(path);

3.1.5 更新数据

更新数据,如果未传入version参数,那么更新当前最新版本,如果传入version则更新指定version,如果version已经变更,则抛出异常。

// 普通更新
client.setData().forPath(path,"新内容".getBytes());
// 指定版本更新
client.setData().withVersion(1).forPath(path);

版本不一直异常信息:

org.apache.zookeeper.KeeperException$BadVersionException: KeeperErrorCode = BadVersion for

3.1.6 异步接口

在使用以上针对节点的操作API时,我们会发现每个接口都有一个inBackground()方法可供调用。此接口就是Curator提供的异步调用入口。对应的异步处理接口为BackgroundCallback。此接口指提供了一个processResult的方法,用来处理回调结果。其中processResult的参数event中的getType()包含了各种事件类型,getResultCode()包含了各种响应码。

重点说一下inBackground的以下接口:

public T inBackground(BackgroundCallback callback, Executor executor);

此接口就允许传入一个Executor实例,用一个专门线程池来处理返回结果之后的业务逻辑。

3.2 完整代码

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;
import java.util.concurrent.Executors;

public class CuratorTest {

    private static RetryPolicy retryPolicy  = new ExponentialBackoffRetry(1000,3);
    private static CuratorFramework client = CuratorFrameworkFactory.builder()
            .connectString("hadoop1:2181,hadoop2:2181,hadoop3:2181")
            .sessionTimeoutMs(3000)
            .connectionTimeoutMs(5000)
            .retryPolicy(retryPolicy)
            .build();

    public static void main(String[] args) throws Exception{
        /**
         * 创建会话
         * */
        client.start();

        /**
         * 同步创建节点
         * 注意:
         *      1.除非指明创建节点的类型,默认是持久节点
         *      2.ZooKeeper规定:所有非叶子节点都是持久节点,所以递归创建出来的节点,
         *          只有最后的数据节点才是指定类型的节点,其父节点是持久节点
         * */

        //创建一个初始内容为空的节点
        client.create().forPath("/China");
        //创建一个初始内容不为空的节点
        client.create().forPath("/Korea","jinzhengen".getBytes());
        //创建一个初始内容为空的临时节点
        client.create().withMode(CreateMode.EPHEMERAL).forPath("America");
        //创建一个初始内容不为空的临时节点,可以实现递归创建
        client.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL)
                .forPath("Japan","xiaoriben".getBytes());


        /**
         *  异步创建节点
         *
         * 注意:如果自己指定了线程池,那么相应的操作就会在线程池中执行,如果没有指定,
         *   那么就会使用Zookeeper的EventThread线程对事件进行串行处理
         * */
        client.create().withMode(CreateMode.EPHEMERAL).inBackground(new BackgroundCallback() {
            public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
                System.out.println("当前线程:" + Thread.currentThread().getName() + ",code:"
                + event.getResultCode() + ",type:" + event.getType());
            }
        },Executors.newFixedThreadPool(10)).forPath("/async-China");


        client.create().withMode(CreateMode.EPHEMERAL).inBackground(new BackgroundCallback() {
            public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
                System.out.println("当前线程:" + Thread.currentThread().getName() + ",code:"
                        + event.getResultCode() + ",type:" + event.getType());
            }
        }).forPath("/async-America");

        /**
         * 获取节点内容
         * */
        byte[] data = client.getData().forPath("/Korea");
        System.out.println(new String(data));
        //传入一个旧的stat变量,来存储服务端返回的最新的节点状态信息
        byte[] data2 = client.getData().storingStatIn(new Stat()).forPath("/Korea");
        System.out.println(new String(data2));

        /**
         * 更新数据
         * */
        Stat stat = client.setData().forPath("/Korea");
        client.setData().withVersion(4).forPath("/Korea", "jinsanpangzi".getBytes());

        /**
         * 删除节点
         * */
        //只能删除叶子节点
        client.delete().forPath("/China");
        //删除一个节点,并递归删除其所有子节点
        client.delete().deletingChildrenIfNeeded().forPath("/aa");
        //强制指定版本进行删除
        client.delete().withVersion(4).forPath("/Korea");
        //注意:由于一些网络原因,上述的删除操作有可能失败,使用guaranteed(),
        // 如果删除失败,会记录下来,只要会话有效,就会不断的重试,直到删除成功为止
        client.delete().guaranteed().forPath("/America");
        
        
        Thread.sleep(Integer.MAX_VALUE);


    }

}





参考

《curator笔记-分布式锁的实现与原理》
《zookeeper curator之我见》
《基于Apache Curator框架的ZooKeeper使用详解》
[《
讨论QQ:1586558083

目录

简介
版本
项目组件
Maven依赖
案例及功能说明
创建会话
重试策略
创建节点
删除节点
读取数据
更新数据
异步接口
完整代码

正文

本文参考自https://blog.csdn.net/wo541075754/article/details/69138878?utm_source=gold_browser_extension

https://www.cnblogs.com/java-zhao/p/7350945.html

回到顶部
简介
Curator是Netflix公司开源的一套Zookeeper客户端框架。了解过Zookeeper原生API都会清楚其复杂度。Curator帮助我们在其基础上进行封装、实现一些开发细节,包括接连重连、反复注册Watcher和NodeExistsException等。目前已经作为Apache的顶级项目出现,是最流行的Zookeeper客户端之一。从编码风格上来讲,它提供了基于Fluent的编程风格支持。

除此之外,Curator还提供了Zookeeper的各种应用场景:Recipe、共享锁服务、Master选举机制和分布式计数器等。

具体信息可以参考Apache官网提供的关于Curator的资料信息

回到顶部
版本
目前Curator有2.x.x和3.x.x两个系列的版本,支持不同版本的Zookeeper。其中Curator 2.x.x兼容Zookeeper的3.4.x和3.5.x。而Curator 3.x.x只兼容Zookeeper 3.5.x,并且提供了一些诸如动态重新配置、watch删除等新特性。

回到顶部
项目组件
名称 描述
Recipes Zookeeper典型应用场景的实现,这些实现是基于Curator Framework。
Framework Zookeeper API的高层封装,大大简化Zookeeper客户端编程,添加了例如Zookeeper连接管理、重试机制等。
Utilities 为Zookeeper提供的各种实用程序。
Client Zookeeper client的封装,用于取代原生的Zookeeper客户端(ZooKeeper类),提供一些非常有用的客户端特性。
Errors Curator如何处理错误,连接问题,可恢复的例外等。
回到顶部
Maven依赖
Curator的jar包已经发布到Maven中心,由以下几个artifact的组成。根据需要选择引入具体的artifact。但大多数情况下只用引入curator-recipes即可。

GroupID/Org ArtifactID/Name 描述
org.apache.curator curator-recipes 所有典型应用场景。需要依赖client和framework,需设置自动获取依赖。
org.apache.curator curator-framework 同组件中framework介绍。
org.apache.curator curator-client 同组件中client介绍。
org.apache.curator curator-test 包含TestingServer、TestingCluster和一些测试工具。
org.apache.curator curator-examples 各种使用Curator特性的案例。
org.apache.curator curator-x-discovery 在framework上构建的服务发现实现。
org.apache.curator curator-x-discoveryserver 可以喝Curator Discovery一起使用的RESTful服务器。
org.apache.curator curator-x-rpc Curator framework和recipes非java环境的桥接。

根据上面的描述,开发人员大多数情况下使用的都是curator-recipes的依赖,此依赖的maven配置如下:

复制代码

org.apache.curator curator-recipes 2.12.0 复制代码 由于版本兼容原因,采用了2.x.x的最高版本。

回到顶部
案例及功能说明
创建会话
Curator的创建会话方式与原生的API和ZkClient的创建方式区别很大。Curator创建客户端是通过CuratorFrameworkFactory工厂类来实现的。其中,此工厂类提供了三种创建客户端的方法。
前两种方法是通过newClient来实现,仅参数不同而已。

public static CuratorFramework newClient(String connectString, RetryPolicy retryPolicy)

public static CuratorFramework newClient(String connectString, int sessionTimeoutMs, int connectionTimeoutMs, RetryPolicy retryPolicy)
使用上面方法创建出一个CuratorFramework之后,需要再调用其start()方法完成会话创建。
实例代码:

RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
CuratorFramework client = CuratorFrameworkFactory.newClient(“127.0.0.1:2181”,retryPolicy);
client.start();
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
CuratorFramework client = CuratorFrameworkFactory.newClient(“127.0.0.1:2181”,
5000,1000,retryPolicy);
client.start();
其中参数RetryPolicy提供重试策略的接口,可以让用户实现自定义的重试策略。默认提供了以下实现,分别为ExponentialBackoffRetry、BoundedExponentialBackoffRetry、RetryForever、RetryNTimes、RetryOneTime、RetryUntilElapsed。

进一步查看源代码可以得知,其实这两种方法内部实现一样,只是对外包装成不同的方法。它们的底层都是通过第三个方法builder来实现的。
实例代码:

复制代码
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
private static CuratorFramework Client = CuratorFrameworkFactory.builder()
.connectString(“hadoop1:2181,hadoop2:2181,hadoop3:2181”)
.sessionTimeoutMs(3000)
.connectionTimeoutMs(5000)
.retryPolicy(retryPolicy)
.build();
client.start();

复制代码
参数:

connectString:zk的server地址,多个server之间使用英文逗号分隔开
connectionTimeoutMs:连接超时时间,如上是30s,默认是15s
sessionTimeoutMs:会话超时时间,如上是50s,默认是60s
retryPolicy:失败重试策略
ExponentialBackoffRetry:构造器含有三个参数 ExponentialBackoffRetry(int baseSleepTimeMs, int maxRetries, int maxSleepMs)
baseSleepTimeMs:初始的sleep时间,用于计算之后的每次重试的sleep时间,
计算公式:当前sleep时间=baseSleepTimeMs*Math.max(1, random.nextInt(1<<(retryCount+1)))
maxRetries:最大重试次数
maxSleepMs:最大sleep时间,如果上述的当前sleep计算出来比这个大,那么sleep用这个时间
其他,查看org.apache.curator.RetryPolicy接口的实现类
start()会阻塞到会话创建成功为止。
重试策略
上面的例子中使用到了ExponentialBackoffRetry重试策略实现。此策略先给定一个初始化sleep时间baseSleepTimeMs,在此基础上结合重试次数,通过以下代码计算当前需要的sleep时间:

long sleepMs = baseSleepTimeMs * Math.max(1, random.nextInt(1 << (retryCount + 1)));
if ( sleepMs > maxSleepMs ){
sleepMs = maxSleepMs;
}
随着重试次数的增加,计算出的sleep时间也会越来越大。如果超过maxSleepMs则使用maxSleepMs的时间。其中maxRetries限制了最大的尝试次数。

创建节点
Curator创建节点的方法也是基于Fluent风格编码,原生API中的参数很多都转化为一层层的方法调用来进行设置。下面简单介绍一下常用的几个节点创建场景。
(1)创建一个初始内容为空的节点

client.create().forPath(path);
Curator默认创建的是持久节点,内容为空。
(2)创建一个包含内容的节点

client.create().forPath(path,“我是内容”.getBytes());
Curator和ZkClient不同的是依旧采用Zookeeper原生API的风格,内容使用byte[]作为方法参数。
(3)创建临时节点,并递归创建父节点

client.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL).forPath(path);
此处Curator和ZkClient一样封装了递归创建父节点的方法。在递归创建父节点时,父节点为持久节点。

删除节点
删除节点的方法也是基于Fluent方式来进行操作,不同类型的操作调用新增不同的方法调用即可。
(1)删除一个子节点

client.delete().forPath(path);
(2)删除节点并递归删除其子节点

client.delete().deletingChildrenIfNeeded().forPath(path);
(3)指定版本进行删除

client.delete().withVersion(1).forPath(path);
如果此版本已经不存在,则删除异常,异常信息如下。

org.apache.zookeeper.KeeperException$BadVersionException: KeeperErrorCode = BadVersion for
(4)强制保证删除一个节点

client.delete().guaranteed().forPath(path);
只要客户端会话有效,那么Curator会在后台持续进行删除操作,直到节点删除成功。比如遇到一些网络异常的情况,此guaranteed的强制删除就会很有效果。

读取数据
读取节点数据内容API相当简单,Curator提供了传入一个Stat,使用节点当前的Stat替换到传入的Stat的方法,查询方法执行完成之后,Stat引用已经执行当前最新的节点Stat。

// 普通查询
client.getData().forPath(path);
// 包含状态查询
Stat stat = new Stat();
client.getData().storingStatIn(stat()).forPath(path);
更新数据
更新数据,如果未传入version参数,那么更新当前最新版本,如果传入version则更新指定version,如果version已经变更,则抛出异常。

// 普通更新
client.setData().forPath(path,“新内容”.getBytes());
// 指定版本更新
client.setData().withVersion(1).forPath(path);
版本不一直异常信息:

org.apache.zookeeper.KeeperException$BadVersionException: KeeperErrorCode = BadVersion for
异步接口
在使用以上针对节点的操作API时,我们会发现每个接口都有一个inBackground()方法可供调用。此接口就是Curator提供的异步调用入口。对应的异步处理接口为BackgroundCallback。此接口指提供了一个processResult的方法,用来处理回调结果。其中processResult的参数event中的getType()包含了各种事件类型,getResultCode()包含了各种响应码。

重点说一下inBackground的以下接口:

public T inBackground(BackgroundCallback callback, Executor executor);
此接口就允许传入一个Executor实例,用一个专门线程池来处理返回结果之后的业务逻辑。

完整代码
复制代码
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;
import java.util.concurrent.Executors;

public class CuratorTest {

private static RetryPolicy retryPolicy  = new ExponentialBackoffRetry(1000,3);
private static CuratorFramework client = CuratorFrameworkFactory.builder()
        .connectString("hadoop1:2181,hadoop2:2181,hadoop3:2181")
        .sessionTimeoutMs(3000)
        .connectionTimeoutMs(5000)
        .retryPolicy(retryPolicy)
        .build();

public static void main(String[] args) throws Exception{
    /**
     * 创建会话
     * */
    client.start();

    /**
     * 同步创建节点
     * 注意:
     *      1.除非指明创建节点的类型,默认是持久节点
     *      2.ZooKeeper规定:所有非叶子节点都是持久节点,所以递归创建出来的节点,
     *          只有最后的数据节点才是指定类型的节点,其父节点是持久节点
     * */

    //创建一个初始内容为空的节点
    client.create().forPath("/China");
    //创建一个初始内容不为空的节点
    client.create().forPath("/Korea","jinzhengen".getBytes());
    //创建一个初始内容为空的临时节点
    client.create().withMode(CreateMode.EPHEMERAL).forPath("America");
    //创建一个初始内容不为空的临时节点,可以实现递归创建
    client.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL)
            .forPath("Japan","xiaoriben".getBytes());


    /**
     *  异步创建节点
     *
     * 注意:如果自己指定了线程池,那么相应的操作就会在线程池中执行,如果没有指定,
     *   那么就会使用Zookeeper的EventThread线程对事件进行串行处理
     * */
    client.create().withMode(CreateMode.EPHEMERAL).inBackground(new BackgroundCallback() {
        public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
            System.out.println("当前线程:" + Thread.currentThread().getName() + ",code:"
            + event.getResultCode() + ",type:" + event.getType());
        }
    },Executors.newFixedThreadPool(10)).forPath("/async-China");


    client.create().withMode(CreateMode.EPHEMERAL).inBackground(new BackgroundCallback() {
        public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
            System.out.println("当前线程:" + Thread.currentThread().getName() + ",code:"
                    + event.getResultCode() + ",type:" + event.getType());
        }
    }).forPath("/async-America");

    /**
     * 获取节点内容
     * */
    byte[] data = client.getData().forPath("/Korea");
    System.out.println(new String(data));
    //传入一个旧的stat变量,来存储服务端返回的最新的节点状态信息
    byte[] data2 = client.getData().storingStatIn(new Stat()).forPath("/Korea");
    System.out.println(new String(data2));

    /**
     * 更新数据
     * */
    Stat stat = client.setData().forPath("/Korea");
    client.setData().withVersion(4).forPath("/Korea", "jinsanpangzi".getBytes());

    /**
     * 删除节点
     * */
    //只能删除叶子节点
    client.delete().forPath("/China");
    //删除一个节点,并递归删除其所有子节点
    client.delete().deletingChildrenIfNeeded().forPath("/aa");
    //强制指定版本进行删除
    client.delete().withVersion(4).forPath("/Korea");
    //注意:由于一些网络原因,上述的删除操作有可能失败,使用guaranteed(),
    // 如果删除失败,会记录下来,只要会话有效,就会不断的重试,直到删除成功为止
    client.delete().guaranteed().forPath("/America");
    
    
    Thread.sleep(Integer.MAX_VALUE);


}

}
复制代码

分类: Zookeeper, Hadoop
好文要顶 关注我 收藏该文
扎心了,老铁
关注 - 55
粉丝 - 1954
+加关注
30
« 上一篇: Python学习之路 (六)爬虫(五)爬取拉勾网招聘信息
» 下一篇: HBase学习之路 (一)HBase基础介绍
posted @ 2018-03-29 11:33 扎心了,老铁 阅读(32104) 评论(0) 编辑 收藏 举报
刷新评论刷新页面返回顶部
登录后才能查看或发表评论,立即 登录 或者 逛逛 博客园首页
【推荐】百度智能云618年中大促,限时抢购,新老用户同享超值折扣
【推荐】大型组态、工控、仿真、CAD\GIS 50万行VC++源码免费下载!
【推荐】618好物推荐:基于HarmonyOS和小熊派BearPi-HM Nano的护花使者
【推荐】阿里云爆品销量榜单出炉,精选爆款产品低至0.55折
【推荐】限时秒杀!国云大数据魔镜,企业级云分析平台

编辑推荐:
· WebGIS vs WebGL 图形编程
· .Net Core with 微服务 - Consul 注册中心
· 为什么选择 ASP.NET Core
· 从 Vehicle-ReId 到 AI 换脸,应有尽有,解你所惑
· CSS ::marker 让文字序号更有意思

最新新闻:
· 雅虎移动MVNO虚拟运营商推出一年多就宣告停业
· Linux内核维护者在邮件列表点名华为开发者提交的补丁有刷KPI嫌疑
· Google Gmail更新广告暗藏《怪奇物语4》精彩剧透
· 八成选择支付赎金的组织会再次遭到勒索软件攻击
· 华为开发者被批评在内核刷 KPI
» 更多新闻…
公告
昵称: 扎心了,老铁
园龄: 3年9个月
粉丝: 1954
关注: 55
+加关注
< 2021年6月 >
日 一 二 三 四 五 六
30 31 1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 1 2 3
4 5 6 7 8 9 10
随笔分类
Azkaban(3)
CDH(9)
Flume(3)
Hadoop(82)
HBase(11)
Hive(21)
Java NIO(1)
JAVAEE(11)
JAVASE(23)
Java基础加强(7)
JVM(1)
JVM虚拟机(1)
Kafka(5)
Mybatis框架(2)
MySql(6)
更多
随笔档案
2018年11月(4)
2018年10月(9)
2018年8月(9)
2018年6月(3)
2018年5月(34)
2018年4月(58)
2018年3月(58)
2018年2月(2)
2018年1月(31)
2017年12月(8)
2017年11月(6)
2017年10月(4)
2017年9月(9)
最新评论

  1. Re:Spark项目之电商用户行为分析大数据平台之(六)用户访问session分析模块介绍
    楼主,这个项目的视频你还有吗

–东京雪梨
2. Re:Kafka学习之路 (五)Kafka在zookeeper中的存储
2018年的文章啊,遗憾没有早点拜读。谢谢。 5篇看完了,不过,对 leader 属于谁 有些困惑?topic 还是 partition? topic会指定 partition 数量,partitio…
–2021$10W
3. Re:Kafka学习之路 (五)Kafka在zookeeper中的存储
厉害了

–dolans
4. Re:Spark学习之路 (二十一)SparkSQL的开窗函数和DataSet
666

–pigpigmann
5. Re:Kafka学习之路 (二)Kafka的架构
@几若是 消费组起负载均衡的做用。组会把一条消息分给某个组员,下一条或几条个消息分给另一个组员。这样符合了网文一个消息只能被一个组中的一个组员消费一次的说法。…
–窗外屋上雪_2013
阅读排行榜

  1. Kafka学习之路 (一)Kafka的简介(470668)
  2. Spark学习之路 (一)Spark初识(178723)
  3. Hive学习之路 (一)Hive初识(164594)
  4. Spark学习之路 (三)Spark之RDD(120738)
  5. Sqoop学习之路 (一)(71256)
    评论排行榜
  6. Kafka学习之路 (一)Kafka的简介(23)
  7. Hive学习之路 (十一)Hive的5个面试题(18)
  8. Hadoop学习之路(三)Hadoop-2.7.5在CentOS-6.7上的编译(13)
  9. Kafka学习之路 (三)Kafka的高可用(12)
  10. Spark学习之路 (三)Spark之RDD(11)
    推荐排行榜
  11. Kafka学习之路 (一)Kafka的简介(77)
  12. Hive学习之路 (一)Hive初识(39)
  13. Spark学习之路 (三)Spark之RDD(28)
  14. Kafka学习之路 (二)Kafka的架构(22)
  15. Spark学习之路 (一)Spark初识(18)
    》](https://www.cnblogs.com/qingyunzong/p/8666288.html#_label2)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值