写点什么

Zookeeper.02 - API

用户头像
insight
关注
发布于: 2021 年 03 月 14 日
Zookeeper.02 - API

zkCli API

创建

创建节点


create /app1# 创建节点并为节点设置值 create /app1 "test"
复制代码

创建临时结点

create -e /lock
复制代码


创建临时结点之后,其他客户端就无法创建相同的结点,当 Zookeeper 崩溃或创建的客户端退出之后,这个临时结点会自动消失。


删除

删除节点

delete /app1
复制代码


删除节点及其所有子节点

deleteall /app1
复制代码


设置节点中的数据

设置一个节点的数据

set /app1 "test"
复制代码


监控节点

监控一个节点

stat -w /lock
复制代码


  • stat:返回 znode 的信息

  • -w:对这个节点进行 watch,当节点发生变化,就会收到通知。


监控一个目录下的节点

ls -w /workers
复制代码


是否存在

判断节点是否存在

exists
复制代码


获取

获得一个节点的数据

get [-s] [-v] /app1
复制代码


  • -s:获取节点的状态

  • -v:对节点进行 watch


获取节点下的所有子节点


getChildren
复制代码


这其中,existsgetDatagetChildren 属于读操作。Zookeeper 客户端在请求读操作的时候,可以选择是否设置 Watch


使用基本操作实现一个简单的分布式锁

  1. 客户端 A 使用 create -e /lock,创建一个临时节点 /lock, 表示创建一个锁。

  2. 此时客户端 B 再尝试去创建,就会创建失败。

  3. 此时客户端 B 可以进行 watch 操作:stat -w /lock

  4. 当客户端 A 删除或退出之后,/lock 节点被释放,此时客户端 B 会收到通知。

  5. 然后客户端 B 就可以创建节点 /lock 了。


Java API

Zookeeper 类

Zookeeper Java 代码主要使用 orgapache.zookeeper.Zookeeper 这个类使用 ZooKeeper 服务。

ZooKeeper(connectString,sessionTimeout,watcher)
复制代码


  • connectString:使用逗号分隔的列表,每个 ZooKeeper 节点是一个 host:port 对,host 是机器名或者 IP 地址,port 是 ZooKeeper 节点对客户端提供服务的端口号。客户端会任意选取 connectString 中的一个节点建立连接。

  • sessionTimeout:session timeout 时间。

  • watcher:用于接收到来自 ZooKeeper 集群的事件。


主要方法

  • create(path,data,flags):创建一个给定路径的 znode,并在 znode 保存 data[]的数据,flags 指定 znode 的类型

  • delete(path,version):如果给定 path 上的 znode 的版本和给定的 version 匹配,删除 znode.

  • exists(path,watch):判断给定 path 上的 znode 是否存在,并在 znode 设置一个 watch

  • getData(path,watch):返回给定 path 上的 znode 数据,并在 znode 设置一个 watch

  • setData(path,data,version):如果给定 path 上的 znode 的版本和给定的 version 匹配,设置 znode 数据。

  • getChildren(path,watch):返回给定 path 上的 znode 的孩子 znode 名字,并在 znode 设置一个 watch.

  • sync(path):把客户端 session 连接节点和 leader 节点进行同步。


方法说明

  • 所有读取 znode 数据的 API 都可以设置一个 watch 用来监控 znode 的变化。

  • 所有更新 znode 数据的 API 都有两个版本:无条件更新版本和条件更新版本。如果 version 为-1,更新为无条件更新。否则只有给定的 version 和 znode 当前的 version 一样,才会进行更新,这样的更新是条件更新。

  • 所有的方法都有同步和异步两个版本。同步版本的方法发送请求给 zookeeper 并等待服务器的响应。异步版本把请求放入客户端的请求队列,然后马上返回。异步版本通过 callback 来接受来自服务端的响应。


getData

有以下三个获取 znode 数据的方法:

  1. byte[] getData(String path,boolean watch,stat stat)同步方法。

  2. void getData(String path,boolean watch,DataCallback cb,object ctx)异步方法。

  3. void getData(String path,Watcher watcher,DataCallback cb,Object ctx)异步方法。


setData

  1. Stat setData(String path,byte[]data,int version)同步版本。

  2. void setData(String path,byte[]data,int version,statCallback cb,Object ctx)异步版本。


Zk 中会出现的异常

所有同步执行的 API 方法都有可能抛出以下两个异常:

  • KeeperException:表示 zooKeeper 服务端出错。KeeperException 的子类 ConnectionLossException 表示客户端和当前连接的 zookeeper 节点断开了连接。网络分区和 zooKeeper 节点失败都会导致这个异常出现。发生此异常的时机可能是在 zooKeeper 节点处理客户端请求之前,也可能是在 zooKeeper 节点处理客户端请求之后。出现 ConnectionLossException 异常之后,客户端会进行自动重新连接,但是我们必须要检查我们以前的客户端请求是否被成功执行。

  • InterruptedException:表示方法被中断了。我们可以使用 Thread.interrupt()来中断 API 的执行。


使用条件更新避免并发错误

条件更新的原理和 CAS 是一样的,通过版本号的方式来实现乐观锁,从而避免并发更新时出现数据更新错误的问题。


下面用一个场景来说明这个问题:

设想用 znode /c 实现一个 counter,使用 set 命令来实现自增 1 操作。

  1. 客户端 1 通过 set 实现/c 的自增 1,此时客户端 1 中 /c 的值为 1

  2. 客户端 2 获取到了值之后,也通过 set 实现 /c 的自增 1,此时 /c 值为 2。

  3. 如果客户端 1 使用的是无条件更新,c 就会更新为 2,没有实现自增 1。


使用条件更新,可以避免对数据基于过期的数据进行数据更新操作。

  1. 客户端 1 把/c 更新到版本 1,实现/c 的自增 1。

  2. 客户端 2 把/c 更新到版本 2,实现/c 的自增 1。

  3. 客户端 1 不知道/c 已经被客户端 2 更新过了,还用过时的版本 1 是去更新 /c ,此时因为版本不匹配,就会发生更新失败。



用户头像

insight

关注

不要混淆行动与进展、忙碌与多产。 2018.11.17 加入

永远都是初学者

评论

发布
暂无评论
Zookeeper.02 - API