Zookeeper.02 - API
zkCli API
创建
创建节点
创建临时结点
创建临时结点之后,其他客户端就无法创建相同的结点,当 Zookeeper 崩溃或创建的客户端退出之后,这个临时结点会自动消失。
删除
删除节点
删除节点及其所有子节点
设置节点中的数据
设置一个节点的数据
监控节点
监控一个节点
stat:返回 znode 的信息
-w
:对这个节点进行 watch,当节点发生变化,就会收到通知。
监控一个目录下的节点
是否存在
判断节点是否存在
获取
获得一个节点的数据
-s
:获取节点的状态-v
:对节点进行 watch
获取节点下的所有子节点
这其中,exists
,getData
,getChildren
属于读操作。Zookeeper 客户端在请求读操作的时候,可以选择是否设置 Watch
使用基本操作实现一个简单的分布式锁
客户端 A 使用
create -e /lock
,创建一个临时节点/lock
, 表示创建一个锁。此时客户端 B 再尝试去创建,就会创建失败。
此时客户端 B 可以进行 watch 操作:
stat -w /lock
当客户端 A 删除或退出之后,
/lock
节点被释放,此时客户端 B 会收到通知。然后客户端 B 就可以创建节点
/lock
了。
Java API
Zookeeper 类
Zookeeper Java 代码主要使用 orgapache.zookeeper.Zookeeper 这个类使用 ZooKeeper 服务。
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 设置一个 watchgetData(path,watch)
:返回给定 path 上的 znode 数据,并在 znode 设置一个 watchsetData(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 数据的方法:
byte[] getData(String path,boolean watch,stat stat)
同步方法。void getData(String path,boolean watch,DataCallback cb,object ctx)
异步方法。void getData(String path,Watcher watcher,DataCallback cb,Object ctx)
异步方法。
setData
Stat setData(String path,byte[]data,int version)
同步版本。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 通过 set 实现/c 的自增 1,此时客户端 1 中 /c 的值为 1
客户端 2 获取到了值之后,也通过 set 实现 /c 的自增 1,此时 /c 值为 2。
如果客户端 1 使用的是无条件更新,c 就会更新为 2,没有实现自增 1。
使用条件更新,可以避免对数据基于过期的数据进行数据更新操作。
客户端 1 把/c 更新到版本 1,实现/c 的自增 1。
客户端 2 把/c 更新到版本 2,实现/c 的自增 1。
客户端 1 不知道/c 已经被客户端 2 更新过了,还用过时的版本 1 是去更新 /c ,此时因为版本不匹配,就会发生更新失败。
评论