文章目录

  • Curator客户端
    • 创建会话
    • 创建节点
    • 获取节点和数据
    • 更新数据
    • 删除节点
    • 事务
    • 节点存在
    • 事件监听
    • 其他工具类
  • 开发测试

Curator客户端

  1. Curator包含了几个包:

    • curator-framework:对zookeeper的底层api的一些封装
    • curator-client:提供一些客户端的操作,例如重试策略等
    • curator-recipes:封装了一些高级特性,如:Cache事件监听、选举、分布式锁、分布式计数器、分布式Barrier等
  2. 版本
    • The are currently two released versions of Curator, 2.x.x and 3.x.x:
    • Curator 2.x.x - compatible with both ZooKeeper 3.4.x and ZooKeeper 3.5.x
    • Curator 3.x.x - compatible only with ZooKeeper 3.5.x and includes support for new features such as dynamic reconfiguration, etc.
  3. Curator主要解决了以下问题
    • 封装ZooKeeper clientZooKeeper server之间的连接处理
    • 提供了一套Fluent风格的操作API
    • 提供ZooKeeper各种应用场景(recipe, 比如共享锁服务, 集群领导选举机制)的抽象封装
  4. 这里使用的版本
    • 服务端Zookeeper版本:3.4.6
    • Curator版本:compile "org.apache.curator:curator-recipes:2.11.0"

创建会话

  1. 创建会话

         @Testpublic void testCreateClient() throws Exception{String connectString = "zk-master:2180,zk-slave1:2182,zk-slave2:2183";int sessionTimeoutMs = 25000;int connectionTimeoutMs = 5000;/***   失去连接重试策略*    baseSleepTimeMs 初始sleep时间*    maxRetries    最大重试次数*    maxSleepMs    最大sleep时间*    当前sleep时间=baseSleepTimeMs*Math.mac(1,random.next(1)) << (retryCount+1)*/int baseSleepTimeMs;int maxRetries;int maxSleepMs;RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);//第一种方式,使用Builder fluent风格的API方式创建CuratorFramework curatorFramework1 = CuratorFrameworkFactory.builder().connectString(connectString).sessionTimeoutMs(sessionTimeoutMs).connectionTimeoutMs(connectionTimeoutMs).retryPolicy(retryPolicy).build();CuratorFrameworkState state1 = curatorFramework1.getState();//zk-curator - LATENTlogger.info(state1.toString());//当连接状态变化时触发curatorFramework1.getConnectionStateListenable().addListener(new ConnectionStateListener() {@Overridepublic void stateChanged(CuratorFramework curatorFramework, ConnectionState connectionState) {//连接状态事件:truelogger.info("连接状态事件:{}",connectionState.isConnected());}});//完成会话的创建curatorFramework1.start();//第二种方式,使用静态工厂方式创建,此方式本质上还是通过第一种方式创建CuratorFramework curatorFramework2 =CuratorFrameworkFactory.newClient(connectString,sessionTimeoutMs,connectionTimeoutMs,retryPolicy);CuratorFrameworkState state2 = curatorFramework2.getState();//zk-curator - LATENTlogger.info(state2.toString());/*** 临时客户端:*      一定时间不活动后连接会被关闭,使用buildTemp()创建*/CuratorTempFramework curatorFramewor3 = CuratorFrameworkFactory.builder().connectString(connectString).sessionTimeoutMs(sessionTimeoutMs).connectionTimeoutMs(connectionTimeoutMs).retryPolicy(retryPolicy).buildTemp(2000,TimeUnit.SECONDS);//.buildTemp();TimeUnit.SECONDS.sleep(20);}
    

创建节点

  1. 创建节点

      @Testpublic void testCreateZnode() throws Exception {String connectString = "zk-master:2180,zk-slave1:2182,zk-slave2:2183";int sessionTimeoutMs = 25000;int connectionTimeoutMs = 5000;String rootPath = "jannal-create";RetryPolicy retryPolicy = new ExponentialBackoffRetry(4000, 3);CuratorFramework curatorFramework = CuratorFrameworkFactory.builder().connectString(connectString).sessionTimeoutMs(sessionTimeoutMs).connectionTimeoutMs(connectionTimeoutMs).retryPolicy(retryPolicy).namespace(rootPath) //客户端对zk上的数据节点的操作都是基本此根节点进行的.build();//完成会话创建curatorFramework.start();//创建一个初始内容为空的znode,默认创建的是持久节点curatorFramework.create().forPath("/userEmpty");//创建一个附带内容的znodecuratorFramework.create().forPath("/userData", "我是jannal".getBytes(Charsets.UTF_8));//创建一个临时节点curatorFramework.create().withMode(CreateMode.EPHEMERAL).forPath("/userTemp", "jannal".getBytes(Charsets.UTF_8));//自动递归创建父节点creatingParentsIfNeeded()curatorFramework.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/user/password", "123456".getBytes(Charsets.UTF_8));curatorFramework.getCuratorListenable().addListener(new CuratorListener() {@Overridepublic void eventReceived(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {}});ExecutorService executorService = Executors.newFixedThreadPool(2);CountDownLatch countDownLatch = new CountDownLatch(1);/*** 在原生的zookeeper客户端中,所有异步通知事件处理都是通过EventThread这个* 线程处理的(串行处理所有事件的通知)。一旦发生复杂的处理单元就会消耗很长事件* 从而影响其他事件的处理,Curator可以使用线程池来处理,如果不指定线程池* 则默认使用EventThread来处理*/curatorFramework.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL).inBackground(new BackgroundCallback() {@Overridepublic void processResult(CuratorFramework client, CuratorEvent event) throws Exception {logger.info(event.toString());countDownLatch.countDown();}},executorService).forPath("/user2","jannal2".getBytes(Charsets.UTF_8));countDownLatch.await();executorService.shutdown();}
    

获取节点和数据

  1. 获取节点和数据

        @Testpublic void testGetZnode() throws Exception {String connectString = "zk-master:2180,zk-slave1:2182,zk-slave2:2183";int sessionTimeoutMs = 25000;int connectionTimeoutMs = 5000;String rootPath = "jannal-get";RetryPolicy retryPolicy = new ExponentialBackoffRetry(4000, 3);CuratorFramework client = CuratorFrameworkFactory.builder().connectString(connectString).sessionTimeoutMs(sessionTimeoutMs).connectionTimeoutMs(connectionTimeoutMs).retryPolicy(retryPolicy).namespace(rootPath).build();client.start();client.create().creatingParentsIfNeeded().forPath("/user/username/jannal", "jannal123".getBytes(Charsets.UTF_8));//获取数据byte[] bytes = client.getData().forPath("/user/username/jannal");Assert.assertEquals("jannal123", new String(bytes, Charsets.UTF_8));//读取一个节点的数据内容,同时获取到该节点的statStat stat = new Stat();bytes = client.getData().storingStatIn(stat).forPath("/user/username/jannal");logger.info(ToStringBuilder.reflectionToString(stat));client.create().creatingParentsIfNeeded().forPath("/user/username1", "abc".getBytes(Charsets.UTF_8));client.create().creatingParentsIfNeeded().forPath("/user/username2", "def".getBytes(Charsets.UTF_8));//获取节点的子节点路径List<String> strings = client.getChildren().forPath("/user");//[username2, username1, username]logger.info(strings.toString());}

更新数据

  1. 更新数据

        @Testpublic void testSetZnode() throws Exception {String connectString = "zk-master:2180,zk-slave1:2182,zk-slave2:2183";int sessionTimeoutMs = 25000;int connectionTimeoutMs = 5000;String rootPath = "jannal-update";RetryPolicy retryPolicy = new ExponentialBackoffRetry(4000, 3);CuratorFramework curatorFramework = CuratorFrameworkFactory.builder().connectString(connectString).sessionTimeoutMs(sessionTimeoutMs).connectionTimeoutMs(connectionTimeoutMs).retryPolicy(retryPolicy).namespace(rootPath) //客户端对zk上的数据节点的操作都是基本此根节点进行的.build();curatorFramework.start();String path = "/user/password";curatorFramework.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/user/password", "123456".getBytes(Charsets.UTF_8));byte[] bytes = curatorFramework.getData().forPath(path);Assert.assertEquals("123456", new String(bytes, Charsets.UTF_8));Stat stat = curatorFramework.setData().forPath(path, "abcd".getBytes(Charsets.UTF_8));bytes = curatorFramework.getData().forPath(path);Assert.assertEquals("abcd", new String(bytes, Charsets.UTF_8));//更新一个节点的数据内容,强制指定版本进行更新curatorFramework.setData().withVersion(stat.getVersion()).forPath(path, "abcde".getBytes());}

删除节点

  1. 在删除一个节点时,由于网络原因,导致删除操作失败。这个异常在有些场景下是致命的,比如Master选举(先创建后删除),针对这个问题Curator引入了一种重试机制,即如果我们调用了guaranteed(),那么只要客户端有效,就会在后台反复重试,直到节点删除成功。

  2. 删除节点示例

        @Testpublic void testDeleteZnode() throws Exception {String connectString = "zk-master:2180,zk-slave1:2182,zk-slave2:2183";int sessionTimeoutMs = 25000;int connectionTimeoutMs = 5000;String rootPath = "jannal-delete";RetryPolicy retryPolicy = new ExponentialBackoffRetry(4000, 3);CuratorFramework client = CuratorFrameworkFactory.builder().connectString(connectString).sessionTimeoutMs(sessionTimeoutMs).connectionTimeoutMs(connectionTimeoutMs).retryPolicy(retryPolicy).namespace(rootPath).build();client.start();client.create().creatingParentsIfNeeded().forPath("/user/username/jannal", "jannal123".getBytes(Charsets.UTF_8));client.create().creatingParentsIfNeeded().forPath("/user2/username/jannal", "jannal123".getBytes(Charsets.UTF_8));client.create().creatingParentsIfNeeded().forPath("/user3/username/jannal", "jannal123".getBytes(Charsets.UTF_8));//删除节点且递归删除其所有的子节点client.delete().deletingChildrenIfNeeded().forPath("/user");//强制指定版本进行删除client.delete().deletingChildrenIfNeeded().withVersion(0).forPath("/user2");//强制保证删除,只要客户端有效,Curator会在后台持续进行删除操作,直到节点删除成功client.delete().guaranteed().forPath("/user3/username/jannal");}
    

事务

  1. 事务

     /*** inTransaction()开启事务,可以复合create, setData, check, and/or delete* 等操作然后调用commit()作为一个原子操作提交** @throws Exception*/@Testpublic void testTransaction() throws Exception {String connectString = "zk-master:2180,zk-slave1:2182,zk-slave2:2183";int sessionTimeoutMs = 25000;int connectionTimeoutMs = 5000;String rootPath = "jannal-transaction";RetryPolicy retryPolicy = new ExponentialBackoffRetry(4000, 3);CuratorFramework client = CuratorFrameworkFactory.builder().connectString(connectString).sessionTimeoutMs(sessionTimeoutMs).connectionTimeoutMs(connectionTimeoutMs).retryPolicy(retryPolicy).namespace(rootPath).build();client.start();client.inTransaction().create().withMode(CreateMode.EPHEMERAL).forPath("/transaction", "事务".getBytes(Charsets.UTF_8)).and().delete().forPath("/transaction").and().commit();}

节点存在

  1. 判断节点是否存在

     @Testpublic void testExist() throws Exception {String connectString = "zk-master:2180,zk-slave1:2182,zk-slave2:2183";int sessionTimeoutMs = 25000;int connectionTimeoutMs = 5000;String rootPath = "jannal-Exist";RetryPolicy retryPolicy = new ExponentialBackoffRetry(4000, 3);CuratorFramework client = CuratorFrameworkFactory.builder().connectString(connectString).sessionTimeoutMs(sessionTimeoutMs).connectionTimeoutMs(connectionTimeoutMs).retryPolicy(retryPolicy).namespace(rootPath).build();client.start();//节点不存在返回nullStat stat = client.checkExists().forPath("/jannal");Assert.assertEquals(null, stat);logger.info(ToStringBuilder.reflectionToString(stat));}

事件监听

  1. 原生客户端支持通过注册Watch来进行事件监听,但是收到事件通知后每次都需要手动再次注册Watch。Curator引入了Cache来实现对Zookeeper服务端事件的监听,并且自动处理反复注册监听,简化了原生API的繁琐。

  2. Cache分为两类监听

    • 节点监听
    • 子节点监听
  3. NodeCache用于监听指定Zookeeper数据节点本身的变化,数据内容发生变化时,就会回调此方法。

      @Testpublic void testNodeCacheEventListener() throws Exception {String connectString = "zk-master:2180,zk-slave1:2182,zk-slave2:2183";int sessionTimeoutMs = 25000;int connectionTimeoutMs = 5000;String rootPath = "jannal-listener";RetryPolicy retryPolicy = new ExponentialBackoffRetry(4000, 3);CuratorFramework client = CuratorFrameworkFactory.builder().connectString(connectString).sessionTimeoutMs(sessionTimeoutMs).connectionTimeoutMs(connectionTimeoutMs).retryPolicy(retryPolicy).namespace(rootPath).build();client.start();String path = "/user/username/jannal";client.create().creatingParentsIfNeeded().forPath(path, "jannal123".getBytes(Charsets.UTF_8));//是否进行数据压缩boolean dataIsCompressed = false;final NodeCache cache = new NodeCache(client, path, dataIsCompressed);cache.start(true);CountDownLatch countDownLatch = new CountDownLatch(2);cache.getListenable().addListener(new NodeCacheListener() {@Overridepublic void nodeChanged() throws Exception {ChildData currentData = cache.getCurrentData();if (currentData != null) {logger.info("数据发生变更,新数据:{}", new String(currentData.getData(), StandardCharsets.UTF_8));}else{logger.info("数据发生变更,新数据:{},节点可能被删除", currentData, StandardCharsets.UTF_8);}countDownLatch.countDown();}});client.setData().forPath(path, "jannal".getBytes(Charsets.UTF_8));client.delete().deletingChildrenIfNeeded().forPath(path);countDownLatch.await();}
  4. PathChildrenCache用于监听指定Zookeeper数据节点的子节点变化情况。当指定节点的子节点发生变化时,就会回调Listener。Curator无法对二级子节点触发变更事件。比如对/zk-jannal子节点进行监听,当/zk-jannal/user/password节点被创建或者删除的时候,无法触发子节点变更事件

        @Testpublic void testPathChildrenCacheEventListener() throws Exception {String connectString = "zk-master:2180,zk-slave1:2182,zk-slave2:2183";int sessionTimeoutMs = 25000;int connectionTimeoutMs = 5000;String rootPath = "jannal-parent-listener";RetryPolicy retryPolicy = new ExponentialBackoffRetry(4000, 3);CuratorFramework client = CuratorFrameworkFactory.builder().connectString(connectString).sessionTimeoutMs(sessionTimeoutMs).connectionTimeoutMs(connectionTimeoutMs).retryPolicy(retryPolicy).namespace(rootPath).build();client.start();String path = "/user";client.create().creatingParentsIfNeeded().forPath(path, "jannal123".getBytes(Charsets.UTF_8));//是否进行数据压缩boolean dataIsCompressed = false;/*** 是否把节点内容缓存起来,如果配置为true,则client在接收* 到节点列表变更的同时,也能够获取到节点的数据内容,如果为false* 则无法获取节点的数据内容*/boolean cacheData = true;ExecutorService executorService = Executors.newFixedThreadPool(2);CountDownLatch countDownLatch = new CountDownLatch(3);final PathChildrenCache cache = new PathChildrenCache(client, path, cacheData, dataIsCompressed, executorService);/*** BUILD_INITIAL_CACHE 同步初始化客户端的cache,及创建cache后,就从服务器端拉入对应的数据(这个是NodeCache使用的方式)* NORMAL 异步初始化cache* POST_INITIALIZED_EVENT 异步初始化,初始化完成触发事件PathChildrenCacheEvent.Type.INITIALIZED*/cache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE);cache.getListenable().addListener(new PathChildrenCacheListener() {@Overridepublic void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception {ChildData currentData = pathChildrenCacheEvent.getData();//事件类型,可通过判断事件类型来做相应的处理PathChildrenCacheEvent.Type type = pathChildrenCacheEvent.getType();switch (type) {//初始化会触发这个事件case INITIALIZED:logger.info("子类缓存系统初始化完成");break;case CHILD_ADDED://新增子节点/user/usernamelogger.info("新增子节点{}", currentData.getPath());break;case CHILD_UPDATED:// 子节点数据变更[106, 97, 110, 110, 97, 108]logger.info("子节点数据变更{}", new String(currentData.getData(),Charsets.UTF_8));break;case CHILD_REMOVED://子节点数据删除/user/usernamelogger.info("子节点数据删除{}", currentData.getPath());break;}countDownLatch.countDown();}});client.create().creatingParentsIfNeeded().forPath(path+"/username", "jannal123".getBytes(Charsets.UTF_8));TimeUnit.SECONDS.sleep(1);client.setData().forPath(path+"/username", "jannal".getBytes(Charsets.UTF_8));TimeUnit.SECONDS.sleep(1);client.delete().deletingChildrenIfNeeded().forPath(path);countDownLatch.await();}
  5. TreeCache可以监听整个树上的所有节点。即可以监控节点的状态,还监控节点的子节点的状态

        @Testpublic void testTreeCache() throws Exception {String connectString = "zk-master:2180,zk-slave1:2182,zk-slave2:2183";int sessionTimeoutMs = 25000;int connectionTimeoutMs = 5000;String rootPath = "jannal-tree-listener";RetryPolicy retryPolicy = new ExponentialBackoffRetry(4000, 3);CuratorFramework client = CuratorFrameworkFactory.builder().connectString(connectString).sessionTimeoutMs(sessionTimeoutMs).connectionTimeoutMs(connectionTimeoutMs).retryPolicy(retryPolicy).namespace(rootPath).build();client.start();String path = "/user";client.create().creatingParentsIfNeeded().forPath(path, "jannal123".getBytes(Charsets.UTF_8));CountDownLatch countDownLatch = new CountDownLatch(1);TreeCache cache = new TreeCache(client, path);cache.getListenable().addListener(new TreeCacheListener() {@Overridepublic void childEvent(CuratorFramework curatorFramework, TreeCacheEvent treeCacheEvent) throws Exception {TreeCacheEvent.Type type = treeCacheEvent.getType();ChildData childData = treeCacheEvent.getData();switch (type) {//子类缓存系统初始化完成case INITIALIZED:logger.info("子类缓存系统初始化完成");break;case NODE_ADDED://新增子节点/user/usernamelogger.info("新增子节点{}", childData != null ? childData.getPath() : null);break;case NODE_UPDATED:// 子节点数据变更jannal// 子节点数据变更jannal2logger.info("子节点数据变更{}", childData != null ? new String(childData.getData(), Charsets.UTF_8) : null);break;case NODE_REMOVED://子节点数据删除/userlogger.info("子节点数据删除{}", childData != null ? childData.getPath() : null);break;}countDownLatch.countDown();}});cache.start();client.setData().forPath(path, "jannal".getBytes());Thread.sleep(1000);client.setData().forPath(path, "jannal2".getBytes());Thread.sleep(1000);client.delete().deletingChildrenIfNeeded().forPath(path);Thread.sleep(1000 * 2);countDownLatch.await();}
    

其他工具类

  1. Curator提供了一些工具类。比如ZKPathsEnsurePath

  2. ZKPaths提供更简单的API来构建Znode路径、递归创建和删除节点。

  3. EnsurePath提供了一种确保数据节点存在的机制。在分布式环境下,A和B机器都同时创建节点,由于并发操作的存在,可能抛出节点已经存在的异常EnsurePath内部实现就是试图创建指定节点,如果节点存在,那么就不进行任何操作,也不抛出异常,否则正常创建节点。从Curator 2.9.0版本开始此类已经过时,首选 CuratorFramework.create().creatingParentContainersIfNeeded() or CuratorFramework.exists().creatingParentContainersIfNeeded()

  4. 代码示例

        @Testpublic void testOther() throws Exception {String connectString = "zk-master:2180,zk-slave1:2182,zk-slave2:2183";int sessionTimeoutMs = 25000;int connectionTimeoutMs = 5000;String rootPath = "zk-other";RetryPolicy retryPolicy = new ExponentialBackoffRetry(4000, 3);CuratorFramework client = CuratorFrameworkFactory.builder().connectString(connectString).sessionTimeoutMs(sessionTimeoutMs).connectionTimeoutMs(connectionTimeoutMs).retryPolicy(retryPolicy).namespace(rootPath).build();client.start();String path = ZKPaths.fixForNamespace(rootPath, "/user");// 输出:/zk-other/userlogger.info(path);ZKPaths.PathAndNode pathAndNode = ZKPaths.getPathAndNode("/zk-other/user/username");// path:/zk-other/user,node:usernamelogger.info("path:{},node:{}", pathAndNode.getPath(), pathAndNode.getNode());CuratorZookeeperClient zookeeperClient = client.getZookeeperClient();//创建节点ZKPaths.mkdirs(zookeeperClient.getZooKeeper(), "/zk-other/user/password");//获取子节点List<String> sortedChildren = ZKPaths.getSortedChildren(zookeeperClient.getZooKeeper(), "/zk-other");logger.info(sortedChildren.toString());}
    

开发测试

  1. 为了便于开发人员进行zk的开发与测试,可以使用curator-test模块。依赖compile "org.apache.curator:curator-test:2.11.0"

  2. 单元测试

    @Testpublic void testSingleServer() throws Exception {File dataDir = new File(".");TestingServer server = new TestingServer(2000, dataDir);server.start();CuratorFramework curatorFramework = CuratorFrameworkFactory.builder().connectString(server.getConnectString()).sessionTimeoutMs(1000).retryPolicy(new RetryNTimes(3, 1000)).build();curatorFramework.start();System.out.println(curatorFramework.getChildren().forPath("/"));curatorFramework.close();server.stop();}
    
  3. 集群测试

        @Testpublic void testClusterServer() throws Exception {TestingCluster server = new TestingCluster(3);server.start();Thread.sleep(2000);TestingZooKeeperServer leader = null;for (TestingZooKeeperServer zs : server.getServers()) {logger.info(zs.getInstanceSpec().getServerId() + "-");logger.info(zs.getQuorumPeer().getServerState() + "-");logger.info(zs.getInstanceSpec().getDataDirectory().getAbsolutePath());if (zs.getQuorumPeer().getServerState().equals("leading")) {leader = zs;}}//模拟leader挂掉leader.kill();logger.info("leader 挂掉之后");for (TestingZooKeeperServer zs : server.getServers()) {logger.info(zs.getInstanceSpec().getServerId() + "-");logger.info(zs.getQuorumPeer().getServerState() + "-");logger.info(zs.getInstanceSpec().getDataDirectory().getAbsolutePath());}server.stop();}

zookeeper之Curator相关推荐

  1. Zookeeper客户端Curator使用详解

    http://www.jianshu.com/p/70151fc0ef5d Zookeeper客户端Curator使用详解 简介 Curator是Netflix公司开源的一套zookeeper客户端框 ...

  2. 软件架构-zookeeper之curator详解

    为了更好的实现java操作zookeeper服务器,后来出现Curator框架,非常的强大,目前已经是apache的顶级项目,里面提供了更多丰富的操作.例如:session超时重连,主从选举,分布式计 ...

  3. ZooKeeper客户端Curator的基本使用

    前提:ZooKeeper版本:3.4.14      Curator版本:2.13.0 1.什么是Curator Curator是Netflix公司开源的一套zookeeper客户端框架,解决了很多Z ...

  4. Zookeeper框架Curator使用

    原文内容: 文档:Zookeeper框架Curator使用.note 链接:http://note.youdao.com/noteshare?id=a5189de7d4f76a882ef52a6baa ...

  5. 【高级篇】详解Zookeeper客户端Curator

    一.序言 之前分享过一篇关于Curotor的基本应用[基础篇]详解Zookeeper客户端Curator,如果对Curator没有了解的可以看看,本文分享关于Curator的一些高级特性,在监听和le ...

  6. 【基础篇】详解Zookeeper客户端Curator

    一.前言 Zookeeper被广泛应用于分布式环境下各种应用程序的协调,而Curator无疑是Zookeeper客户端中的瑞士军刀,解决了很多Zookeeper客户端非常底层的细节开发工作,包括连接重 ...

  7. ZooKeeper : Curator框架Znode、ACL API介绍

    ZooKeeper : Curator框架Znode.ACL API介绍 在之前的博客中,博主介绍了Curator框架的重试策略和Session API,并且对namespace进行了原理分析: Zo ...

  8. ZooKeeper : Curator框架之分布式锁InterProcessReadWriteLock

    InterProcessReadWriteLock 跨JVM工作的可重入读/写互斥锁,使用Zookeeper来持有锁,所有JVM中使用相同锁路径的所有进程都将实现进程间临界区.这个互斥锁是公平的,每个 ...

  9. 聊聊、Zookeeper 客户端 Curator

    [Curator]   和 ZkClient 一样,Curator 也是开源客户端,Curator 是 Netflix 公司开源的一套框架. <dependency><groupId ...

  10. Zookeeper、Curator

    1. 初识Zookeeper 1.1 Zookeeper概念 Zookeeper是Apache Hadoop项目下的一个子项目,是一个树形目录服务 Zookeeper翻译过来就是动物园管理员,它是用来 ...

最新文章

  1. GDOI2018记录
  2. Haskell / GHC中的“ forall”关键字有什么作用?
  3. 风控特:关系网络特征工程入门实践
  4. 管理之道(三) - 不要吝惜赞美
  5. 三级pc技术_第十九周PC、笔电、数码周边新品汇总:AMD英特尔激战正酣
  6. CSS 小结笔记之滑动门技术
  7. php脚本来创建一个表,PHP - SQL脚本创建器
  8. java 排序算法面试题_面试题: java中常见的排序算法的实现及比较
  9. 排序算法合集 python
  10. 谁偷偷删了你的微信?别慌!一篇Python学习教程帮你都揪出来
  11. java 对象流 乱码,JAVA 中的 IO 流
  12. 转:施炜:铁军组织是怎样炼成的?高能组织=人×管理体系×数字标准
  13. 【新书推荐】【2017.07】创新的雷达技术与应用第一卷:实孔径阵列雷达、成像雷达与无源多基地雷达
  14. 浅墨博客《游戏编程模式》
  15. 2022软工K班结对编程作业
  16. 门诊地图导航怎么做,零成本的医院室内导航解决方案
  17. js通过Ajax传递数组
  18. 发生系统错误 5。拒绝访问。
  19. 飘易关键字排名批量查询工具分享!
  20. CC2540开发入门

热门文章

  1. 浏览器显示无法解析服务器的DNS地址,搜狗浏览器无法解析服务器的DNS地址怎么解决...
  2. 怎么复制黑苹果config配置_黑苹果主机(百分百成功硬件配置)
  3. spark while_while循环怎么理解
  4. 无限天空服务器,滚动的天空无限钻石无限金币版
  5. Android初试--了解和认识Android
  6. Linux简介,linux终端符号含义
  7. MATLAB面向对象_及_AppDesigner使用
  8. 计算机管理的磁盘管理简单卷,小编教你磁盘管理新建简单卷怎么做
  9. Wrapper中ge,gt,lt,le的含义
  10. AI创作教程之如何使用简单的 Web API 和 GPU 支持在 Docker 中运行 Stable Diffusion,在 45 秒内启动用于 Stable Diffusion的 Web API