Zookeeper简介

基本概念

Zookeeper是一个开源的分布式协调服务。其设计目标是将那些复杂的容易出错的分布式一致性服务封装起来,以简单的接口提供给用户使用。它是一个典型的分布式数据一致性的解决方案,分布式应用程序可以基于它实现如:发布/订阅、负载均衡、集群管理、分布式锁、分布式队列等功能。

名词概念

  1. 集群角色

Zookeeper集群中有三种角色:Leader、Follower、Observer。Leader提供读和写服务。Follower和Observer能提供读服务。Observer和Follower的区别就在于Ovserver不参与Leader选举,不参与写操作的过半成功策略。

因此Observer可以在不影响写性能的情况下,提升集群的性能。如果没有Observer的话,一个Leader和N个Follower,如果Follower特别多的话,虽然读性能提高了,但是写性能和选举的性能会受影响。

  1. 会话(session)

客户端会话,一个客户端连接是指客户端和服务端之间的一个TCP长连接。客户端启动的时候,首先会和服务器建立一个TCP长连接,从第一次建立连接开始,会话(session)的生命周期就开始了。通过这个连接,客户端能够通过心跳检测与服务器保持有效的会话,也能够向Zookeeper服务器发送请求,同时还能接受服务器的Watch事件通知。

  1. 数据节点(Znode)

Zookeeper数据模型中的一个单元,我们称之为数据节点。Zookeeper将所有数据存储在内存中,数据模型是一棵树,由斜杠进行分割的路径,就是一个Znode。如/app。每个Znode都能保存自己的数据内容,还会保存属性信息。

4. 版本

每个Znode都有一个叫作Stat的数据结构,Stat里记录了Znode的三个数据版本,分别是version(当前Znode的版本)、cversion(当前Znode子节点的版本)、aversion(当前Znode的ACL版本)

5. Watcher(事件监听器)

Watcher是Zookeeper中一个很重要的特性,Zookeeper允许用户在指定节点上注册一些Watcher,并且在一些特定事件触发的时候,Zookeeper服务端会将事件通知到感兴趣的客户端,该机制是Zookeeper实现分布式协调服务的重要特性。

6. ACL

Zookeeper采用ACL策略来进行权限控制,它定义了五种权限:

  • CREATE:创建子节点的权限
  • READ:获取节点数据和子节点列表的权限
  • WRITE:更新节点数据的权限
  • DELETE:删除子节点的权限
  • ADMIN:设置子节点ACL的权限。

注意:CREATE和DELETE这两种权限是针对子节点的权限控制

Zookeeper命令行

  1. 客户端连接
  1. ./zkCli.sh #连接本地的zookeeper服务器
  2. ./zkCli.sh -server ip:port # 连接远程的服务器

连接成功之后,系统会输出Zookeeper的相关环境及配置信息等信息

  1. 创建节点
  1. create [-s] [-e] [-c] [-t ttl] path [data] [acl]
  2. #创建顺序节点
  3. create -s /cc
  4. #创建临时节点,客户端会话结束后,节点会自动删除
  5. create -e /temp
  6. #创建带内容的节点
  7. create /hi nihao
  1. 读取节点
  1. #ls命令会列出path节点下所有的子节点
  2. ls path
  3. #get命令会查询到path节点的数据内容,加上-s可以查询更详细的信息
  4. get [-s] path
  1. 更新节点
  1. set [-s] [-v version] path data
  2. #修改/abc节点的内容为hello,加上-s会返回更详细的信息
  3. set /abc hello
  1. 删除节点
  1. #删除,如果带上了版本参数,那么删除的时候就会校验版本是否正确,正确才进行删除
  2. delete [-v version] path

Zookeeper 客户端API

官方原生API

  1. <dependency>
  2. <groupId>org.apache.zookeeper</groupId>
  3. <artifactId>zookeeper</artifactId>
  4. <version>3.4.14</version>
  5. </dependency>

很少直接使用了,接口介绍省略

ZkClient API

ZkClient是github上一个开源的zookeeper客户端,在原生API的基础上进行了包装,更加易用。同时还实现了如Session超时重连、Watcher反复注册等功能。

  1. <dependency>
  2. <groupId>com.101tec</groupId>
  3. <artifactId>zkclient</artifactId>
  4. <version>0.2</version>
  5. </dependency>

直接上代码:


  1. public class ClientDemo {
  2. private static final String connectStr="192.168.56.115:2181";
  3. public static void main(String[] args) throws InterruptedException {
  4. // create();
  5. // delete();
  6. // get();
  7. getData();
  8. }
  9. public static void create() throws InterruptedException {
  10. ZkClient zkClient=new ZkClient(connectStr);
  11. //第二个参数,true代表递归创建节点,没有父节点先创建父节点
  12. zkClient.createPersistent("/test/node01",true);
  13. //持久有序的node
  14. zkClient.createPersistentSequential("/test/node02","data");
  15. //临时node
  16. zkClient.createEphemeral("/ephemeral");
  17. }
  18. public static void delete(){
  19. ZkClient zkClient=new ZkClient(connectStr);
  20. //普通删除
  21. zkClient.delete("/test");
  22. //遍历删除,先删除该节点的所有子节点,再删除它本身
  23. zkClient.deleteRecursive("/test");
  24. }
  25. public static void get() throws InterruptedException {
  26. ZkClient zkClient=new ZkClient(connectStr);
  27. List<String> children = zkClient.getChildren("/test");
  28. System.out.println("子节点:"+children);
  29. zkClient.subscribeChildChanges("/watch", new IZkChildListener() {
  30. @Override
  31. public void handleChildChange(String s, List<String> list) throws Exception {
  32. System.out.println(s + " child changed,list:" + list);
  33. }
  34. });
  35. zkClient.createPersistent("/watch");
  36. Thread.sleep(1000);
  37. zkClient.createPersistent("/watch/test");
  38. Thread.sleep(1000);
  39. zkClient.delete("/watch/test");
  40. Thread.sleep(1000);
  41. zkClient.delete("/watch");
  42. }
  43. //获取数据
  44. public static void getData() throws InterruptedException {
  45. ZkClient zkClient=new ZkClient(connectStr);
  46. String path="/abc";
  47. boolean exists = zkClient.exists(path);
  48. System.out.println("节点是否存在:"+exists);
  49. if(!exists){
  50. zkClient.createEphemeral(path,"123");
  51. }
  52. //数据改变监听
  53. zkClient.subscribeDataChanges(path, new IZkDataListener() {
  54. @Override
  55. public void handleDataChange(String s, Object o) throws Exception {
  56. System.out.println("节点:"+s+" 数据被改变:"+o);
  57. }
  58. @Override
  59. public void handleDataDeleted(String s) throws Exception {
  60. System.out.println("节点被删除:"+s);
  61. }
  62. });
  63. //读取数据
  64. Object o = zkClient.readData(path);
  65. System.out.println("读取节点的数据:"+o);
  66. Thread.sleep(3000);
  67. //更新数据
  68. Stat stat = zkClient.writeData(path, "456");
  69. Thread.sleep(3000);
  70. //删除数据
  71. zkClient.delete(path);
  72. Thread.sleep(3000);
  73. }
  74. }

Curator API

Curator是Netflix公司开源的客户端框架。它实现了连接重连、Watcher反复注册、重试策略和NodeExistsException异常解决等等。

  1. <dependency>
  2. <groupId>org.apache.curator</groupId>
  3. <artifactId>curator-framework</artifactId>
  4. <version>2.12.0</version>
  5. </dependency>

直接上代码:


  1. public class CuratorDemo {
  2. private static final String connectStr="192.168.56.115:2181";
  3. private static String path ="/abc";
  4. public static void main(String[] args) throws Exception {
  5. // connect();
  6. // create();
  7. // delete();
  8. // get();
  9. update();
  10. }
  11. public static void connect(){
  12. //连接方式1
  13. /*
  14. 构造器含有三个参数 ExponentialBackoffRetry(int
  15. baseSleepTimeMs, int maxRetries, int maxSleepMs)
  16. baseSleepTimeMs:初始的sleep时间,⽤于计算之后的每次重试的sleep时间,
  17. 计算公式:当前sleep时间=baseSleepTimeMs*Math.max(1,
  18. random.nextInt(1<<(retryCount+1)))
  19. maxRetries:最⼤重试次数
  20. maxSleepMs:最⼤sleep时间,如果上述的当前sleep计算出来⽐这个⼤,那么sleep⽤
  21. 这个时间,默认的最⼤时间是Integer.MAX_VALUE毫秒。
  22. */
  23. RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
  24. CuratorFramework client = CuratorFrameworkFactory.newClient(connectStr, 5000, 3000, retryPolicy);
  25. client.start();
  26. //连接方式2
  27. CuratorFramework Client = CuratorFrameworkFactory.builder()
  28. .connectString("server1:2181,server2:2181,server3:2181")
  29. .sessionTimeoutMs(50000)
  30. .connectionTimeoutMs(30000)
  31. .retryPolicy(retryPolicy)
  32. .build();
  33. client.start();
  34. }
  35. public static void create() throws Exception {
  36. RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
  37. CuratorFramework client = CuratorFrameworkFactory.newClient(connectStr, 5000, 30000, retryPolicy);
  38. client.start();
  39. Thread.sleep(2000);
  40. //创建一个内容为空的节点,curator默认是创建持久节点
  41. // client.create().forPath(path);
  42. //创建一个有内容的节点
  43. client.create().forPath(path,"123".getBytes());
  44. //调用creatingParentsIfNeeded 接口,Curator 就能够自动地递归创建所有需要的父节点
  45. client.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL).forPath("/tt");
  46. }
  47. public static void delete() throws Exception {
  48. RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
  49. CuratorFramework client = CuratorFrameworkFactory.newClient(connectStr, 5000, 30000, retryPolicy);
  50. client.start();
  51. //删除节点
  52. client.delete().forPath(path);
  53. //删除节点,并递归删除子节点
  54. client.delete().deletingChildrenIfNeeded().forPath(path);
  55. //指定版本删除ls
  56. client.delete().withVersion(1).forPath(path);
  57. //强制删除。只要客户端会话有效,那么Curator会在后台持续进⾏删除操作,直到节点删除成功。⽐如遇到⼀些⽹
  58. //络异常的情况,此guaranteed的强制删除就会很有效果
  59. client.delete().guaranteed().forPath(path);
  60. }
  61. public static void get() throws Exception {
  62. RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
  63. CuratorFramework client = CuratorFrameworkFactory.newClient(connectStr, 5000, 30000, retryPolicy);
  64. client.start();
  65. //普通查询
  66. byte[] bytes = client.getData().forPath(path);
  67. System.out.println("节点内容:"+new String(bytes));
  68. // 包含状态查询
  69. Stat stat = new Stat();
  70. byte[] bytes1 = client.getData().storingStatIn(stat).forPath(path);
  71. System.out.println(stat.getVersion());
  72. }
  73. public static void update() throws Exception {
  74. RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
  75. CuratorFramework client = CuratorFrameworkFactory.newClient(connectStr, 5000, 30000, retryPolicy);
  76. client.start();
  77. // 普通更新
  78. client.setData().forPath(path,"新内容".getBytes());
  79. // 指定版本更新 当携带数据版本不⼀致时,无法完成更新操作
  80. // 异常信息:Exception in thread "main" org.apache.zookeeper.KeeperException$BadVersionException: KeeperErrorCode = BadVersion for /abc
  81. client.setData().withVersion(1).forPath(path,"abcd".getBytes());
  82. }

Zookeeper基础入门的更多相关文章

  1. ZooKeeper 基础入门

    什么是ZooKeeper Apache ZooKeeper 是一个开源的实现高可用的分布式协调服务器.ZooKeeper是一种集中式服务,用于维护配置信息,域名服务,提供分布式同步和集群管理.所有这些 ...

  2. Zookeeper基础入门介绍

    什么Zookeeper Zookeeper是一个分布式开源框架,提供了协调分布式应用的基本服务,它向外部应用暴露一组通用服务——分布式同步(Distributed Synchronization).命 ...

  3. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  4. 「译」JUnit 5 系列:基础入门

    原文地址:http://blog.codefx.org/libraries/junit-5-basics/ 原文日期:25, Feb, 2016 译文首发:Linesh 的博客:JUnit 5 系列: ...

  5. .NET正则表达式基础入门

    这是我第一次写的博客,个人觉得十分不容易.以前看别人写的博客文字十分流畅,到自己来写却发现十分困难,还是感谢那些为技术而奉献自己力量的人吧. 本教程编写之前,博主阅读了<正则指引>这本入门 ...

  6. 从零3D基础入门XNA 4.0(2)——模型和BasicEffect

    [题外话] 上一篇文章介绍了3D开发基础与XNA开发程序的整体结构,以及使用Model类的Draw方法将模型绘制到屏幕上.本文接着上一篇文章继续,介绍XNA中模型的结构.BasicEffect的使用以 ...

  7. 从零3D基础入门XNA 4.0(1)——3D开发基础

    [题外话] 最近要做一个3D动画演示的程序,由于比较熟悉C#语言,再加上XNA对模型的支持比较好,故选择了XNA平台.不过从网上找到很多XNA的入门文章,发现大都需要一些3D基础,而我之前并没有接触过 ...

  8. Shell编程菜鸟基础入门笔记

    Shell编程基础入门     1.shell格式:例 shell脚本开发习惯 1.指定解释器 #!/bin/bash 2.脚本开头加版权等信息如:#DATE:时间,#author(作者)#mail: ...

  9. [Spring框架]Spring AOP基础入门总结二:Spring基于AspectJ的AOP的开发.

    前言: 在上一篇中: [Spring框架]Spring AOP基础入门总结一. 中 我们已经知道了一个Spring AOP程序是如何开发的, 在这里呢我们将基于AspectJ来进行AOP 的总结和学习 ...

随机推荐

  1. 《剑指offer》面试题63. 股票的最大利润

    问题描述 假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖该股票一次可能获得的最大利润是多少? 示例 1: 输入: [7,1,5,3,6,4] 输出: 5 解释: 在第 2 天(股票价格 = ...

  2. Sentry 开发者贡献指南 - 数据库迁移

    Django 迁移是我们处理 Sentry 中数据库更改的方式. Django 迁移官方文档:https://docs.djangoproject.com/en/2.2/topics/migratio ...

  3. 【刷题-LeetCode】300. Longest Increasing Subsequence

    Longest Increasing Subsequence Given an unsorted array of integers, find the length of longest incre ...

  4. 【解决了一个小问题】golang go.mod中多了一个斜杠导致replace无效

    replace github.com/sxxx/common_lib/src/ => ../../common_lib/src 修改成 replace github.com/sxxx/commo ...

  5. selenium - 弹出框死活定位不到

    先要确定是不是alert,是才能用,不是的话肯定不能用. 有些弹出框是div层,这种跟平常定位方法一样 有些弹出框是嵌套的iframe层,这种切换iframe就可以了 有些弹出框比较坑,是嵌入的一个窗 ...

  6. 适配器模式(Adapter模式)

    模式的定义与特点 适配器模式(Adapter)的定义如下:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作.适配器模式分为类结构型模式和对象结构型模式 ...

  7. HTML 基础1

    HTML 超文本标记语言 文件后缀html,htm 标签成对出现:开始标签--结束标签 元素内容位于开始标签--结束标签之间(可以有空内容) 空元素<a/> 大小写不敏感 元素,属性 &l ...

  8. python 小兵(10)内置函数

    内置函数(下午讲解) 什么是内置函数?就是python帮我们提供的一个工具,拿过直接用就行,比如我们的print,input,type,id等等.截止到python3.6.2版本 中一共提供了68个内 ...

  9. django入门 03 模板语法

    变量值从views.py传入html 基本语法 {{ abc }} 变量abc外,用双大括号包裹 {% for item in abc %} 语句外,用大括号+百分号包裹 1. 传递字符串 views ...

  10. 原生js获取子元素

    感谢原文作者:归一山人 原文链接:https://www.cnblogs.com/guiyishanren/p/12214757.html 获取子元素的方法有 //获取第一个demo类 dom = d ...