# zookeeper基本应用


<!--more-->


## 1.zk系统模型

在ZooKeeper中，数据信息被保存在⼀个个数据节点上，这些节点被称为znode。ZNode 是Zookeeper 中最⼩数据单位，在 ZNode 下⾯⼜可以再挂 ZNode，这样⼀层层下去就形成了⼀个层次化命名空间 ZNode 树，我们称为 ZNode Tree，它采⽤了类似⽂件系统的层级树状结构进⾏管理，如下图示例

![示意图](https://img.zhaojq.top/20260727091723757.png "示意图")

在 Zookeeper 中，每⼀个数据节点都是⼀个 ZNode，上图根⽬录下有两个节点，分别是：app1 和app2，其中 app1 下⾯⼜有三个⼦节点,所有ZNode按层次化进⾏组织，形成这么⼀颗树，ZNode的节点路径标识⽅式和Unix⽂件系统路径⾮常相似，都是由⼀系列使⽤斜杠（/）进⾏分割的路径表示，开发⼈员可以向这个节点写⼊数据，也可以在这个节点下⾯创建⼦节点。

- znode类型

  Zookeeper节点类型可以分为三⼤类：

  - 持久性节点（Persistent）
  - 临时性节点（Ephemeral）
  - 顺序性节点（Sequential）

  在开发中在创建节点的时候通过组合可以⽣成以下四种节点类型：持久节点、持久顺序节点、临时节点、临时顺序节点。不同类型的节点则会有不同的⽣命周期

  - 持久节点：是Zookeeper中最常⻅的⼀种节点类型，所谓持久节点，就是指节点被创建后会⼀直存在服务器，直到删除操作主动清除
  - 持久顺序节点：就是有顺序的持久节点，节点特性和持久节点是⼀样的，只是额外特性表现在顺序上。顺序特性实质是在创建节点的时候，会在节点名后⾯加上⼀个数字后缀，来表示其顺序。
  - 临时节点：就是会被⾃动清理掉的节点，它的⽣命周期和客户端会话绑在⼀起，客户端会话结束，节点会被删除掉。与持久性节点不同的是，临时节点不能创建⼦节点。
  - 临时顺序节点：就是有顺序的临时节点，和持久顺序节点相同，在其创建的时候会在名字后⾯加上数字后缀。

- 事务id

  ⾸先，先了解，事务是对物理和抽象的应⽤状态上的操作集合。往往在现在的概念中，狭义上的事务通常指的是数据库事务，⼀般包含了⼀系列对数据库有序的读写操作，这些数据库事务具有所谓的ACID特性，即原⼦性（Atomic）、⼀致性（Consistency）、隔离性（Isolation）和持久性（Durability）。

  ⽽在ZooKeeper中，事务是指能够改变ZooKeeper服务器状态的操作，我们也称之为事务操作或更新操作，⼀般包括数据节点创建与删除、数据节点内容更新等操作。对于每⼀个事务请求，ZooKeeper都会为其分配⼀个全局唯⼀的事务ID，⽤ZXID来表示，通常是⼀个64位的数字。每⼀个ZXID对应⼀次更新操作，从这些ZXID中可以间接地识别出ZooKeeper处理这些更新操作请求的全局顺序

- ZNode的状态信息

  整个ZNode节点内容包括两部分：节点数据内容和节点状态信息。图中quota是数据内容，其他的属于状态信息。那么这些状态信息都有什么含义呢？

  > cZxid就是CreateZXID，表示节点被创建时的事务ID。
  > ctime就是CreateTime，表示节点创建时间。
  > mZxid就是ModifiedZXID，表示节点最后⼀次被修改时的事务ID。
  > mtime就是ModifiedTime，表示节点最后⼀次被修改的时间。
  > pZxid表示该节点的⼦节点列表最后⼀次被修改时的事务ID。只有⼦节点列表变更才会更新pZxid，⼦节点内容变更不会更新。
  > cversion表示⼦节点的版本号。
  > dataVersion表示内容版本号。
  > aclVersion标识acl版本
  > ephemeralOwner表示创建该临时节点时的会话sessionID，如果是持久性节点那么值为0 
  > dataLength表示数据⻓度。
  > numChildren表示直系⼦节点数。

- Watcher--数据变更通知

  Zookeeper使⽤Watcher机制实现分布式数据的发布/订阅功能

  ⼀个典型的发布/订阅模型系统定义了⼀种⼀对多的订阅关系，能够让多个订阅者同时监听某⼀个主题对象，当这个主题对象⾃身状态变化时，会通知所有订阅者，使它们能够做出相应的处理。

  在ZooKeeper中，引⼊了Watcher机制来实现这种分布式的通知功能。ZooKeeper允许客户端向服务端注册⼀个Watcher监听，当服务端的⼀些指定事件触发了这个Watcher，那么就会向指定客户端发送⼀个事件通知来实现分布式的通知功能。

  整个Watcher注册与通知过程如图所示。

  ![示意图](https://img.zhaojq.top/20260727091723947.png "示意图")

  Zookeeper的Watcher机制主要包括**客户端线程**、**客户端WatcherManager**、**Zookeeper服务器**三部分。
  具体⼯作流程为：客户端在向Zookeeper服务器注册的同时，会将Watcher对象存储在客户端的
  WatcherManager当中。当Zookeeper服务器触发Watcher事件后，会向客户端发送通知，客户端线程从WatcherManager中取出对应的Watcher对象来执⾏回调逻辑。

- ACL--保障数据的安全

  ookeeper作为⼀个分布式协调框架，其内部存储了分布式系统运⾏时状态的元数据，这些元数据会直接影响基于Zookeeper进⾏构造的分布式系统的运⾏状态，因此，如何保障系统中数据的安全，从⽽避免因误操作所带来的数据随意变更⽽导致的数据库异常⼗分重要，在Zookeeper中，提供了⼀套完善的ACL（AccessControlList）权限控制机制来保障数据的安全。

  我们可以从三个⽅⾯来理解ACL机制：**权限模式（Scheme）**、**授权对象（ID**）、**权限（Permission）**，通常使⽤"scheme:id：permission"来标识⼀个有效的ACL信息。

  - 权限模式：Scheme 

    > 1. ip
    >
    >    IP模式就是通过IP地址粒度来进⾏权限控制，如"ip:192.168.0.110"表示权限控制针对该IP地址，同时IP模式可以⽀持按照⽹段⽅式进⾏配置，如"ip:192.168.0.1/24"表示针对192.168.0.*这个⽹段进⾏权限控制。
    >
    > 2. Digest
    >
    >    Digest是最常⽤的权限控制模式，要更符合我们对权限控制的认识，其使
    >    ⽤"username:password"形式的权限标识来进⾏权限配置，便于区分不同应⽤来进⾏权限控制。当我们通过“username:password”形式配置了权限标识后，Zookeeper会先后对其进⾏SHA-1加密和BASE64编码。
    >
    > 3. World
    >
    >    World是⼀种最开放的权限控制模式，这种权限控制⽅式⼏乎没有任何作⽤，数据节点的访问权限对所有⽤户开放，即所有⽤户都可以在不进⾏任何权限校验的情况下操作ZooKeeper上的数据。另外，World模式也可以看作是⼀种特殊的Digest模式，它只有⼀个权限标识，即“world：anyone”。
    >
    > 4. Super
    >
    >    Super模式，顾名思义就是超级⽤户的意思，也是⼀种特殊的Digest模式。在Super模式下，超级⽤户可以对任意ZooKeeper上的数据节点进⾏任何操作。

  - 授权对象：ID 

    授权对象指的是权限赋予的⽤户或⼀个指定实体，例如IP地址或是机器等。在不同的权限模式下，授权对象是不同的，表中列出了各个权限模式和授权对象之间的对应关系。

  - 权限

    权限就是指那些通过权限检查后可以被允许执⾏的操作。在ZooKeeper中，所有对数据的操作权限分为以下五⼤类：

    - CREATE（C）：数据节点的创建权限，允许授权对象在该数据节点下创建⼦节点。
    - DELETE（D）：⼦节点的删除权限，允许授权对象删除该数据节点的⼦节点。
    - READ（R）：数据节点的读取权限，允许授权对象访问该数据节点并读取其数据内容或⼦节点列表等。
    - WRITE（W）：数据节点的更新权限，允许授权对象对该数据节点进⾏更新操作。
    - ADMIN（A）：数据节点的管理权限，允许授权对象对该数据节点进⾏ACL相关的设置操作。



## 2.命令行操作

```shell
./zkcli.sh连接本地的zookeeper服务器
./zkCli.sh-serverip:port连接指定的服务器
```

- 创建节点

  ```shell
  create [-s] [-e] path data acl 
  其中，-s或-e分别指定节点特性，顺序或临时节点，若不指定，则创建持久节点；acl⽤来进⾏权限控制。
  ```

- 读取节点

  ```shell
  ls path 
  其中，path表示的是指定数据节点的节点路径
  
  get path
  get命令可以获取Zookeeper指定节点的数据内容和属性信息。
  ```

- 更新节点

  ```shell
  set path data [version]
  ```

- 删除节点

  ```shell
  delete path [version]
  ```



## 3.api的使用

Zookeeper的java客户端API使⽤⽅式

Zookeeper作为⼀个分布式框架，主要⽤来解决分布式⼀致性问题，它提供了简单的分布式原语，并且对多种编程语⾔提供了API，所以接下来重点来看下Zookeeper的java客户端API使⽤⽅式

ZookeeperAPI共包含五个包，分别为：

（1）org.apache.zookeeper 

（2）org.apache.zookeeper.data 

（3）org.apache.zookeeper.server 

（4）org.apache.zookeeper.server.quorum 

（5）org.apache.zookeeper.server.upgrade 

其中org.apache.zookeeper，包含Zookeeper类，他是我们编程时最常⽤的类⽂件。这个类是Zookeeper客户端的主要类⽂件。如果要使⽤Zookeeper服务，应⽤程序⾸先必须创建⼀个Zookeeper 实例，这时就需要使⽤此类。⼀旦客户端和Zookeeper服务端建⽴起了连接，Zookeeper系统将会给本次连接会话分配⼀个ID值，并且客户端将会周期性的向服务器端发送⼼跳来维持会话连接。只要连接有效，客户端就可以使⽤ZookeeperAPI来做相应处理了。

示例代码：[https://gitee.com/ixinglan/zookeeper-demo.git](https://gitee.com/ixinglan/zookeeper-demo.git) apidemo



## 4.开源客户端

### 4.1 zkClient

ZkClient是Github上⼀个开源的zookeeper客户端，在Zookeeper原⽣API接⼝之上进⾏了包装，是⼀个更易⽤的Zookeeper客户端，同时，zkClient在内部还实现了诸如Session超时重连、Watcher反复注册等功能

示例代码：[https://gitee.com/ixinglan/zookeeper-demo.git](https://gitee.com/ixinglan/zookeeper-demo.git) zkclientdemo



### 4.2 curator客户端

curator是Netﬂix公司开源的⼀套Zookeeper客户端框架，和ZKClient⼀样，Curator解决了很多Zookeeper客户端⾮常底层的细节开发⼯作，包括连接重连，反复注册Watcher和NodeExistsException异常等，是最流⾏的Zookeeper客户端之⼀。从编码⻛格上来讲，它提供了基于Fluent的编程⻛格⽀持

示例代码：[https://gitee.com/ixinglan/zookeeper-demo.git](https://gitee.com/ixinglan/zookeeper-demo.git) curatordemo

