整套大数据学习资料(视频+笔记)百度网盘无门槛下载:http://www.edu360.cn/news/content?id=3377

14.3.2操作

hadoop 花牛 18℃ 0评论

如表丨4-2所示,ZooKeeper中有9种基本操作。

14-2. ZooKeeper服务的操作

操作

描述

delete

删除一个znode(该znode不能有任何子节点)

exists

测试一个znode是否存在并且査询它的元数据

getACL, setACL

获取/设置一个znodeACL

getChildren

获取一个znode的子节点列表

getData, setData

获取/设置一个znode所保存的数据

sync

将客户端的znode视图与ZooKeeper同步


ZooKeeper
中的更新操作是有条件的。在使用deletesetData操作时必须提供被更新znode的版本号(可以通过exists操作获得)。如果版本号不匹配,则更新操作会失败。更新操作是非阻塞操作,因此一个更新失败 的客户端(由于其他进程同时在更新同一个znode)可以决定是否重试,或执 行其他操作,并不会因此而阻塞其他进程的执行。

虽然ZooKeeper可以被看作是一个文件系统,但出于简单性的需要,有一些文件系统的基本操作被它摒弃   了。由于ZooKeeper中的文件较小并且总是被整体读写,因此没有必要提供打幵、关闭或査找操作。

sync操作与POSIX文件系统中fsync()操作是不同的。如前所述,ZooKeeper中的写操作具有原子性,一个成功的写操作会保证将数据写到ZooKeeper服务器的持久存储介质中。然而,ZooKeeper允许客户端读到的数据滞后于ZooKeeper服务的最新状态,因此客户端可以使用sync操作来获取数据的最新状态。相关详情请参见14.3.4节。

1. 集合更新(Multiupdate)

ZooKeeper中有一个被称为multi的操作,用于将多个基本操作集合成一个操作单元,并确保这些基本操作同时被成功执行,或者同时失败,不会 发生其中部分基本操作被成功执行而其他基本操作失败的情况。 集合更新可以被用于在ZooKeeper中构建需要保持全局一致性的数据结构,例如构建一个无向图。在ZooKeeper中用一个znode来表示无向图中的一个顶点,为了在两个顶点之间添加或删除一条边,我们需要同时更新 两个顶点所分别对应的两个znode,因为每个znode中都有指向对方的引用。如果我们只用ZooKeeper的基本操作来实现边的更新,可能会让其他客户端发现无向图处于不一致的状态,即一个顶点具有指向另一个顶点的引用而对方却没有对应的引用。将针对两个znode的更新操作集合到一个multi操作中可以保证这组更新操作的原子性,也就保证了一对顶点之间不会出现不完整的连接。

2.关于API

对于ZooKeeper客户端来说,主要有两种语言绑定(binding)可以使用:Java C;当然也可以使用PerlPythonRESTcontrib绑定。对于每一种绑定语言来说,在执行操作时都可以选择同步执行或异步执行。我们已 经看过同步执行的Java API。下面是exists操作的签名,它返回一个封装有znode元数据的Stat对象(如果znode不存在,则返回null):

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

ZooKeeper类中同样可以找到异步执行的签名,如下所示:

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

因为所有异步操作的结果都是通过回调来传送的,因此在Java API中异步 方法的返回类型都是void。调用者传递一个回调的实现,当ZooKeeper响应时,该回调方法被调用。在这种情况下,回调采用StatCallback接 口,它有以下方法:

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

其中rc参数是返回代码,对应于KeeperException的代码。每个非零代 码都代表一个异常,在这种情况下,stat参数是nullpathctx参数 对应于客户端传递给exists()方法的参数,用于识别这个回调所响应的请 求。ctx参数可以是任意对象,当path参数不能提供足够的信息时,客户 端可以通过ctx参数来区分不同请求。如果path参数提供了足够的信息,可以将ctx参数设成null

实际上,有两个C语言的共享库。单线程库zookeeper_st只支持异步 API,并且主要在没有pthread库或pthread库不稳定的平台上使用。大部分开发人员都使用多线程库zookeeper_mt,它既支持同步API也支持 异步API。要想进一步了解如何构建和使用C语言API,请参考ZooKeeper 安装目录下wc/c子目录中的文件。

我该使用同步API还是异步API?

两种类型的API提供相同的功能,因此选择哪一种只是风格问题。例 如,如果你习惯于事件驱动的编程模型,则异步API更合适一些。

异步API允许你以流水线方式处理请求,这在某些情况下可以提供更好 的吞吐量。想象一下,你打算读取一大批znode并且分别对它们进行处 理。如果使用同步API,每一个读操作都会阻塞进程,直到该读操作返 回;但如果使用异步API,你可以非常快地启动所有的异步读操作并在另 外一个单独的线程中来处理读操作的返回。

3. 观察触发器 

existsgetChildrengetData这些读操作可以设置观察,这些 观察可以被写操作createdeletesetData触发。ACL相关的操作不参与触发任何观察。当一个观察被触发时会产生一个观察事件,这个观察 和触发它的操作共同决定着观察事件的类型。

•当所观察的znode被创建、删除或其数据被更新时,设置在 exists操作上的观察将被触发。

•当所观察的znode被删除或其数据被更新时,设置在getData操 作上的观察将被触发。创建znode不会触发getData操作上的观 察,因为getData操作成功执行的前提是znode必须已经存在。

•当所观察的znode的一个子节点被创建或删除时,或所观察的 znode自己被删除时,设置在getChildren操作上的观察将会被触发。可以通过观察事件的类型来判断被删除的是znode还是其子节点:NodeDelete 类型代表 znode 被删除,NodeChildrenChanged类型代表一个子节点被删除。

表14-3列出了观察及其触发操作所对应的事件类型。

14-3.观察及其触发操作所对应的事件类型观察触发器

设置观察的操作setDate

创建znode

创建子节点

删除znode

删除子节点

exists

NodeCreated

NodeDeleted

NodeData

Changed

getData

NodeDeleted

NodeData

Changed

getChildren

NodeChildren

NodeDeleted

NodeChildren

Changed

Changed


一个观察事件中包含涉及该事件的
znode的路径,因此对于NodeCreated和 NodeDeleted事件来说,可通过路径来判断哪一个节点被创建或删除。为了能够在NodeChildrenChanged事件发生之后判断是哪些子节点被修改,需要 重新调用getChildren来获取新的子节点列表。与之类似,为了能够在NodeDataChanged事件之后获取新的数据,需要调用getData。在这两种情况下,从收到观察事件到执行读操作(getChildrengetData)期间,znode的状态可能会发生改变,在写程序的时候必须牢记这一点。

4. ACL列表

每个znode被创建时都会带有一个ACL列表,用于决定谁可以对它执行何种操作。

ACL依赖于ZooKeeper的客户端身份验证机制。ZooKeeper提供了以下几种身份验证方式:

• Digest通过用户名和密码来识别客户端

• sasl通过Kerberos来识别客户端

• Ip通过客户端的[P地址来识别客户端

在建立一个ZooKeeper会话之后,客户端可以对自己进行身份验证。虽然 znodeACL列表会要求所有的客户端是经过验证的,但ZooKeeper的身 份验证过程却是可选的,客户端必须自己进行身份验证来支持对znode的访问。这里有一个使用digest方式(用户名和密码)进行身份验证的例子:

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

每个ACL都是身份验证方式、符合该方式的一个身份和一组权限的组合。例如,如果我们打算给IP地址为10.0.0.1的客户端对某个znode的读权限,可以使用ip验证方式、10.0.0.1READ权限在该znode上设置一个ACL。在Java语言中,我们可以如下所示来创建这个ACL对象:

new ACL(Perms.READ,

new Id("ip' "10.0.0.1"));

14-4列出了一个完整的权限集合。注意exists操作并不受ACL权限的限制,因此任何客户端都可以调用exists来检索一个znode的状态或查询一个znode是否存在。

14-4. ACL权限

ACL权限 CREATE

允许的操作 create(子节点)

READ

getChildren

getData

WRITE

setData

DELETE

cfelete(子节点)

ADMIN

setACL


在类ZooDefs.Ids中有一些预定义的ACL, OPEN_ACL_UNSAFE是其中之

一,它将所有的权限(不包括ADMIN权限)授予每个人。此外,ZooKeeper还支持插入式身份验证机制,如果需要的话,它可以集成 第三方的身份验证系统。

ZooKeeper服务有两种不同的运行模式。一种是“独立模式”(standalone mode),即只有一个ZooKeeper服务器。这种模式较为简单,比较适合于测 试环境(甚至可以在单元测试中采用),但是不能保证高可用性和可恢复性。 在生产环境中的ZooKeeper通常以“复制模式”(replicated mode)运行于一 个计算机集群上,这个计算机集群被称为一个“集合体”(ensemble)。 ZooKeeper通过复制来实现高可用性,只要集合体中半数以上的机器处干可 用状态,它就能够提供服务。例如,在一个有5个节点的集合体中,任意2 台机器出现故障,都可以保证服务继续,因为剩下的3台机器超过了半 数。注意,6个节点的集合体也只能够容忍2台机器出现故障,因为如果3台机器出现故障,剩下的3台机器没有超过集合体的半数。出于这个原 因,一个集合体通常包含奇数台机器。

从概念上来说,ZooKeeper是非常简单的:它所做的就是确保对znode树的 每一个修改都会被复制到集合体中超过半数的机器上。如果少于半数的机器出现故障,则最少有一台机器会保存最新的状态,其余的副本最终也会 更新到这个状态。

然而,这个简单想法的实现却不简单。ZooKeeper使用了Zab协议,该协议包括两个可以无限重复的阶段。 

1. 阶段1:领导者选举

集合体中的所有机器通过一个选择过程来选出一台被称为“领导者”(leader)的机器,其他的机器被称为“跟随者”(follower)。一旦半数以上(或指定数 量)的跟随者已经将其状态与领导者同步,则表明这个阶段已经完成。

2. 阶段2:原子广播

所有的写请求都会被转发给领导者,再由领导者将更新广播给跟随者。当半数以上的跟随者已经将修改持久化之后,领导者才会提交这个更新,然后客户端才会收到一个更新成功的响应。这个用来达成共识的协议被设计 成具有原子性,因此每个修改要么成功要么失败。这类似于数据库中的两阶段提交协议。


ZooKeeper 是否使用 Paxos?

否。ZooKeeper的Zab协议不同于众所周知的Paxos算法(Leslie Lamport, wPaxos Made Simple,ACM SIGACT News [Distributed Computing Column) 32, 4 [Whole Number 121,December 2001] 51-58.)。虽然有些类似,但是 Zab在操作方面是不同的,例如它依靠TCP来保证其消息的顺序。

有关Zab的描述,可参见Benjamin Reed和Flavio Junqueira的论文“A simple totally ordered broadcast protoc〇r'(LADIS 2008, in: Proceedings of the 2nd Workshop on Large-Scale Distributed Systems and Middleware, Article 2, New York, NY, USA, 2008. ACM)。

Google 的 Chubby 锁服务(Mike Burrows, “The Chubby Lock Service for LooselyCoupled Distributed Systems,,5 November 2006, http://labs.google.com/ papers/ 是基于 Paxos 的,它的功能与 ZooKeeper 的功能类似。

如果领导者出现故障,其余的机器会选出另外-个领导者,并和新的领导者一起继续提供服务。随后,如果之前的领导者恢复正常,会成为一个跟随者。领导者选举的过程是非常快的,根据一个已公布的结果来看,只需要大约200毫秒,因此在领导者选举的过程中不会出现系统性能的明显降低。

在更新内存中的znode树之前,集合体中的所有机器都会先将更新写入磁盘。任何一台机器都可以为读请求提供服务,并且由于读请求只涉及内存检索,因此非常快。

转载请注明:全栈大数据 » 14.3.2操作

喜欢 (0)or分享 (0)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址