Zookeeper——Java客户端API使用

2022-09-05 12:36:20

Zookeeper作为一个分布式服务框架,主要用来解决分布式数据一致性问题,它对多种编程语言提供了API。下面重点来学习Zookeeper的Java客户端API使用。

创建会话
客户端可以通过Zookeeper(org.apache.zookeeper.Zookeeper)实例来连接Zookeeper服务器,有如下4种构造方式:

ZooKeeper(String connectString, int sessionTimeout, Watcher watcher)
ZooKeeper(String connectString, int sessionTimeout, Watcher watcher,
            boolean canBeReadOnly)
ZooKeeper(String connectString, int sessionTimeout, Watcher watcher,
            long sessionId, byte[] sessionPasswd)
ZooKeeper(String connectString, int sessionTimeout, Watcher watcher,
            long sessionId, byte[] sessionPasswd, boolean canBeReadOnly)

Zookeeper构造方式参数说明:

参数名说明
connectString指Zookeeper服务器列表,由英文状态逗号分开的host:port字符串组成,每一个都代表一台Zookeeper机器,如,192.168.1.1:2181,192.168.1.2:2181,192.168.1.3:2181。也可在connectString中设置客户端连接上Zookeeper后的根目录,方法是在host:port字符串后添加上这个根目录,如192.168.1.1:2181,192.168.1.2:2181,192.168.1.3:2181/zk-book,这样就指定了该客户端连接上Zookeeper服务器后,所有对Zookeeper的操作都会基于这个根目录。如客户端对/foo/bar的操作,都会指向节点/zk-book/foo/bar—这个目录也叫Chroot,即客户端隔离命名空间。
sessionTimeout指会话的超时时间,是一个以“毫秒”为单位的整型值。在Zookeeper中有会话的概念,在一个会话周期内,Zookeeper客户端和服务端之间通过心跳检测机制来维持会话的有效性,一旦在sessionTimeout时间内没有进行有效的心跳检测,会话就消失。
watcher默认的Watcher事件通知处理器,该参数也可以设置为null
canBeReadOnlyboolean类型,用于标识当前会话是否支持“read-only(只读)”模式。默认情况下,在Zookeeper集群中,一个机器如果和集群中过半及以上机器失去了网络连接,那么这个机器将不再处理客户端请求(包括读写请求)。但是在某些使用场景下,当Zookeeper服务器发生此类故障的时候,我们还是希望Zookeeper的服务器能够提供读服务(当然写服务肯定无法提供)——这就是Zookeeper的“read-only”模式。
sessionId和sessionPasswd分别代表会话ID和会话秘钥。这两个参数能够唯一确定一个会话,同时客户端使用这两个参数可以实现客户端会话复用,从而达到恢复会话的效果。具体方法是,第一次连上Zookeeper服务器时,通过调用Zookeeper对象实例的以下两个接口,即可获得当前会话的ID和秘钥:long getSessionId() ;byte[] getSessionPasswd();获取到这两个参数值之后,就可以在下次创建Zookeeper对象实例的时候传入构造方法了。

注意:Zookeeper客户端和服务端会话的建立是一个异步的过程,也就是说在程序中,构造方法会在处理完客户端初始化工作后立即返回,在大多数情况下,此时并没有真正建立好一个可用的会话,在会话的生命周期中处于“CONNECTING”的状态。
当该会话真正创建完毕后,Zookeeper服务端会向会话对应的客户端发送一个事件通知,以告知客户端,客户端只有在获取这个通知后,才算真正建立了会话。

创建节点
客户端创建一个数据节点,接口如下:

create(final String path, byte data[], List<ACL> acl,CreateMode createMode)
create(final String path, byte data[], List<ACL> acl,
              CreateMode createMode,  StringCallback cb, Object ctx)

这两个接口分别以同步和异步的方式创建节点,参数说明如下:

参数名说明
path需要创建的数据节点的节点路径,如,/zk-book/foo
data[]一个字节数组,是节点创建后的初始内容
acl节点的ACL策略
createMode节点类型,是一个枚举类型,通常有4种可选节点类型:
持久(PERSISTENT)
持久顺序(PERSISTENT_SEQUENTIAL)
临时(EPHEMERAL)
临时顺序(EPHEMERAL_SEQUENTIAL)
cb注册一个异步回调函数。需要我们实现StringCallback接口,对如下方法重写:void processResult(int rc, String path, Object ctx, String name);当服务端节点创建完毕后,Zookeeper客户端会自动调用这个方法,这样就可以处理相关的业务逻辑了。
ctx用于传递一个对象,可以在回调方法执行的时候使用,通常是放一个上下文(Context)信息

注意,无论是同步还是异步接口,Zookeeper都不支持递归创建,即无法在父节点不存在的情况下创建一个子节点。如果一个节点已经存在,那么创建同名节点时,会抛出NodeExistsException异常。同时,在临时节点下面是无法创建子节点的。
关于权限控制,如果你的应用场景没有太高的权限要求,那么可以不关注这个参数,只需要在acl参数中传入参数Ids.OPEN_ACL_UNSAFE,这就表明之后对这个节点的任何操作都不受权限控制。

删除节点
客户端删除一个节点,接口如下:

void delete(final String path, int version)
void delete(final String path, int version, VoidCallback cb,Object ctx)

这两个API分别是同步和异步的删除接口,API方法参数说明如下:

参数名说明
path指定数据节点的节点路径,即API调用的目的是删除该节点
version指定节点的数据版本,即表明本次删除操作是针对该数据版本进行的
cb注册一个异步回调函数
ctx用于传递上下文信息的对象

在Zookeeper中,只允许删除叶子节点,即如果一个节点存在至少一个子节点的话,那么该节点将无法被直接删除,必须先删除掉其所有子节点。

读取数据
getChildren
客户端可以通过Zookeeper的API来获取一个节点的所有子节点,如下8个接口:

List<String> getChildren(final String path, Watcher watcher)
List<String> getChildren(String path, boolean watch)
void getChildren(final String path, Watcher watcher,ChildrenCallback cb, Object ctx)
void getChildren(String path, boolean watch, ChildrenCallback cb,Object ctx)
List<String> getChildren(final String path, Watcher watcher,Stat stat)
List<String> getChildren(String path, boolean watch, Stat stat)
void getChildren(final String path, Watcher watcher,Children2Callback cb, Object ctx)
void getChildren(String path, boolean watch, Children2Callback cb,Object ctx)

参数说明如下:

参数名说明
path指定数据节点的节点路径,即API调用的目的是获取该节点的子节点列表
watcher注册的Watcher。一旦在本次子节点获取之后,子节点列表发生变更的话,那么就会向客户端发送通知。该参数允许传入null
watch表明是否需要注册一个Watcher
cb注册一个异步回调函数
ctx用于传递上下文信息的对象
stat指定数据节点的节点状态信息。用法是在接口中传入一个旧的stat变量,该stat变量会在方法执行过程中,被来自服务端响应的新stat对象替换

getData
客户端可以通过Zookeeper的API来获取一个节点的数据内容,如下4个接口:

byte[] getData(final String path, Watcher watcher, Stat stat)
byte[] getData(String path, boolean watch, Stat stat)
void getData(final String path, Watcher watcher,DataCallback cb, Object ctx)
void getData(String path, boolean watch, DataCallback cb, Object ctx)

参数说明:

参数名说明
path指定数据节点的节点路径,即API调用的目的是获取该节点的数据内容
watcher注册的Watcher。一旦之后节点内容有变更,就会向客户端发送通知。该参数允许传入null
stat指定数据节点的节点状态信息。用法是在接口中传入一个旧的stat变量,该stat变量会在方法执行过程中,被来自服务端响应的新stat对象替换
watch表明是否需要注册一个Watcher
cb注册一个异步回调函数
ctx用于传递上下文信息的对象

更新数据
客户端可以通过Zookeeper的API来更新一个节点的数据内容,有如下两个接口:

Stat setData(final String path, byte data[], int version)
void setData(final String path, byte data[], int version,StatCallback cb, Object ctx)

方法参数说明:

参数名说明
path指定数据节点的节点路径,即API调用的目的是更新该节点的数据内容
data[]一个字节数组,即需要使用该数据内容来覆盖节点现在的数据内容
version指定节点的数据版本,即表明本次更新操作是针对该数据版本进行的
cb注册一个异步回调函数
ctx用于传递上下文信息的对象

注意:更新的时候,在这里指定数据版本的意义何在呢?
原来Zookeeper的setData接口中的version参数正是由CAS原理衍化而来,在调用更新操作的时候,就可以添加version参数,该参数对应于CAS原理中的“预期值”,表明是针对该数据版本进行更新的。假如一个客户端试图进行更新操作,它会携带上次获取到的version值进行更新。而如果在这段时间内,Zookeeper服务器上该节点的数据恰好已经被其他客户端更新了,那么其数据版本一定也发生了变化,因此肯定与客户端携带的version无法匹配,于是便无法更新成功——因此可以有效地避免一些分布式更新的并发问题。

检测节点是否存在
客户端可以通过Zookeeper的API来检测一个节点是否存在,如下4个接口:

public Stat exists(final String path, Watcher watcher)
public Stat exists(String path, boolean watch)
public void exists(final String path, Watcher watcher,StatCallback cb,
                                         Object ctx)
public void exists(String path, boolean watch, StatCallback cb, Object ctx)

方法参数说明:

参数名说明
path指定数据节点的节点路径,即API调用的目的是检测该节点是否存在
watcher注册的Watcher,用于监听以下三类事件:节点被创建、节点被删除、节点被更新
watch指定是否复用Zookeeper中默认的Watcher
cb注册一个异步回调函数
ctx用于传递上下文信息的对象
  • 作者:uk8692
  • 原文链接:https://blog.csdn.net/uk8692/article/details/88539494
    更新时间:2022-09-05 12:36:20