返回介绍

操作 Operations

发布于 2025-01-04 01:04:22 字数 6315 浏览 0 评论 0 收藏 0

下面的表格中列出了 9 种 ZooKeeper 的操作。

操作说明
createCreates a znode (the parent znode must already exist)
deleteDeletes a znode (the znode must not have any children)
existsTests whether a znode exists and retrieves its metadata
getACL, setACLGets/sets the ACL for a znode
getChildrenGets a list of the children of a znode
getData, setDataGets/sets the data associated with a znode
syncSynchronizes a client’s view of a znode with ZooKeeper

调用 deletesetData 操作时,我们必须指定一个 znode 版本号(version number),即我们必须指定我们要删除或者更新 znode 数据的哪个版本。如果版本号不匹配,操作将会失败。失败的原因可能是在我们提交之前,该 znode 已经被修改过了,版本号发生了增量变化。那么我们该怎么办呢?我可以考虑重试,或者调用其他的操作。例如,我们提交更新失败后,可以重新获取 znode 当前的数据,看看当前的版本号是什么,再做更新操作。

ZooKeeper 虽然可以被看作是一个文件系统,但是由于 ZooKeeper 文件很小,所以没有提供像一般文件系统所提供的 openclose 或者 seek 操作。

注意
这里的 sync 操作与 POSIX 文件系统的 fsync() 操作是不同的。就像我们早前讲过的,ZooKeeper 的写操作是原子性的,一个成功的写操作只保证数据被持久化到大多数 ZooKeeper 的服务器存储上。所以读操作可能会读取不到最新状态的数据, sync 操作用来让 client 强制所访问的 ZooKeeper 服务器上的数据状态更新到最新状态。我们会在《一致性 Consistentcy》一节中详细介绍。

批量更新 Multiupdate

ZooKeeper 支持将一些原始的操作组合成一个操作单元,然后执行这些操作。那么这种批量操作也是具有原子性的,只可能有两种执行结果,成功和失败。批量操作单元中的操作,不会出现一些操作执行成功,一些操作执行失败的情况,即要么都成功,要么都失败。

Multiupdate 对于绑定一些结构化的全局变量很有用处。例如绑定一个无向图(undirected graph)。无向图的顶点(vertex)由 znode 来表示。添加和删除边(edge)的操作,由修改边的两个关联 znode 来实现。如果我们使用 ZooKeeper 的原始的操作来实现对边(edge)的操作,那么就有可能产生两个 znode 修改不一致的情况(一个修改成功,一个修改失败)。那么我们将修改两个 znode 的操作放入到一个 Multi 修改单元中,就能够保证两个 znode,要么都修改成功,要么都修改失败。这样就能够避免修改无向图的边时产生修改不一致的现象。

APIs

ZooKeeper 客户端使用的核心编程语言有 JAVA 和 C;同时也支持 Perl、Python 和 REST。执行操作的方式呢,分为同步执行和异步执行。我们之前已经见识过了同步的 Java API 中的 exists


public Stat exists(String path, Watcher watcher) throws KeeperException,
 InterruptedException

下面代码则是异步方式的 exists :

public void exists(String path, Watcher watcher, StatCallback cb, Object ctx)

Java API 中,异步的方法的返回类型都是 void ,而操作的返回的结果将传递到回调对象的回调函数中。回调对象将实现 StatCallback 接口中的一个回调函数,来接收操作返回的结果。函数接口如下:

public void processResult(int rc, String path, Object ctx, Stat stat);

参数 rc 表示返回码,请参考 KeeperException 中的定义。在 stat 参数为 null 的情况下,非 0 的值表示一种异常。参数 pathctx 与客户端调用的 exists 方法中的参数相等,这两个参数通常用来确定回调中获得的响应是来至于哪个请求的。参数 ctx 可以是任意对象,只有当 path 参数不能消灭请求的歧义时才会用到。如果不需要参数 ctx ,可以设置为 null。

应该使用同步 API 还是异步 API 呢?
两种 API 提供了相同的功能,需要使用哪种 API 取决于你程序的模式。例如,你设计的程序模式是一个事件驱动模式的程序,那么你最好使用异步 API。异步 API 也可以被用在追求一个比较好的数据吞吐量的场景。想象一下,如果你需要得去大量的 znode 数据,并且依靠独立的进程来处理他们。如果使用同步 API,每次读取操作都会被阻塞住,直到返回结果。不如使用异步 API,读取操作可以不必等待返回结果,继续执行。而使用另外的线程来处理返回结果。

观察模式触发器 Watch triggers

读操作,例如: existsgetChildrengetData 会在 znode 上开启观察模式,并且写操作会触发观察模式事件,例如: createdeletesetData 。ACL(Access Control List) 操作不会启动观察模式。观察模式被触发时,会生成一个事件,这个事件的类型取决于触发他的操作:

  • exists 启动的观察模式,由创建 znode,删除 znode 和更新 znode 操作来触发。
  • getData 启动的观察模式,由删除 znode 和更新 znode 操作触发。创建 znode 不会触发,是因为 getData 操作成功的前提是 znode 必须已经存在。
  • getChildren 启动的观察模式,由子节点创建和删除,或者本节点被删除时才会被触发。我们可以通过事件的类型来判断是本节点被删除还是子节点被删除: NodeChildrenChanged 表示子节点被删除,而 NodeDeleted 表示本节点删除。
---Watch trigger    
Watch creationcreate znodecreate childdelete znodedelete childsetData
existsNodeCreated-NodeDeleted-NodeDataChanged
getData--NodeDeleted-NodeDataChanged
getChildren-getChildrenNodeDeletedNodeChildrenChanged-

事件包含了触发事件的 znode 的 path,所以我们通过 NodeCreatedNodeDeleted 事件就可以知道哪个 znode 被创建了或者删除了。如果我们需要在 NodeChildrenChanged 事件发生后知道哪个子节点被改变了,我们就需要再调用一次 getChildren 来获得一个新的子节点列表。与之类似,在 NodeDataChanged 事件发生后,我们需要调用 getData 来获得新的数据。我们在编写程序时,会在接收到事件通知后改变 znode 的状态,所以我们一定要清楚的记住 znode 的状态变化。

ACLs 访问控制操作

znode 的创建时,我们会给他一个 ACL(Access Control List),来决定谁可以对 znode 做哪些操作。

ZooKeeper 通过鉴权来获得客户端的身份,然后通过 ACL 来控制客户端的访问。鉴权方式有如下几种:

  • digest 使用用户名和密码方式
  • sasl 使用 Kerberos 鉴权
  • ip 使用客户端的 IP 来鉴权

客户端可以在与 ZooKeeper 建立会话连接后,自己给自己授权。授权是并不是必须的,虽然 znode 的 ACL 要求客户端必须是身份合法的,在这种情况下,客户端可以自己授权来访问 znode。下面的例子,客户端使用用户名和密码为自己授权:

 zk.addAuthInfo("digest", "tom:secret".getBytes());

ACL 是由鉴权方式、鉴权方式的 ID 和一个许可(permession)的集合组成。例如,我们想通过一个 ip 地址为 10.0.0.1 的客户端访问一个 znode。那么,我们需要为 znode 设置一个 ACL,鉴权方式使用 IP 鉴权方式,鉴权方式的 ID 为 10.0.0.1,只允许读权限。使用 JAVA 我们将像如下方式创建一个 ACL 对象:

new ACL(Perms.READ,new Id("ip", "10.0.0.1"));

所有的许可权限将在下表中列出。请注意, exists 操作不受 ACL 的控制,所以任何一个客户端都可以通过 exists 操作来获得任何 znode 的状态,从而得知 znode 是否真的存在。

ACL permissionPermitted operations
CREATEcreate (a child znode)
READgetChildren,getData
WRITEsetData
DELETEdelete (a child znode)
ADMINsetACL

ZooDefs.Ids 类中,有一些 ACL 的预定义变量,包括 OPEN_ACL_UNSAFE ,这个设置表示将赋予所有的许可给客户端(除了 ADMIN 的许可)。

另外,我们可以使用 ZooKeeper 鉴权的插件机制,来整合第三方的鉴权系统。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文