• 进入"运维那点事"后,希望您第一件事就是阅读“关于”栏目,仔细阅读“关于Ctrl+c问题”,不希望误会!

ZooKeeper工作原理阐述(一)

消息队列 彭东稳 8年前 (2016-10-27) 24801次浏览 已收录 0个评论

Zookeeper是一个维护配置信息、命名、提供分布式同步和提供群组服务的集中式服务。这些各种类型的服务以某种形式被分布式应用程序使用。每当应用程序实现这些服务都不可避免的引入大量的修复BUG和竞争条件的工作。因为实现这些服务的难度在于应用最初通常跳过它们,使应用程序在发生变化时不易维护并难以管理。即使做对了,当应用程序已经部署后,不同服务的实现也将会导致管理的复杂性。

Zookeeper是一个高性能的分布式系统的协调服务。它暴露公共的服务:像命名、配置管理、同步、和群组服务在一个简单的接口里,所以你没有必要从头开始实现它们。你可以使用现成的Zookeeper去实现共识、群组管理、领导人选举和业务协议。并且你可以在它的基础之上建立自己的特定的需求。

Zookeeper的设计目的?

1)简单

Zookeeper允许程序通过一个共享的类似于标准文件系统的有组织的分层命名空间分布式处理协调。命名空间包括:数据寄存器 – 在Zookeeper中叫znodes, 它和文件、目录一样。和一般文件系统的不同之处是,它的设计就是为了存储,Zookeeper的数据保持在内存中,这就意味着它可以实现高吞吐量和低延迟的数据。

Zookeeper的实现提供了一个优质的高性能、高可用,严格的访问顺序。Zookeeper的性能方面意味着它可以用于大型的分布式系统。可靠性方面防止它成为一个单点故障。严格的顺序意味着可以在客户端实现复杂的同步原件。

2)复制

zookeeper像分布式处理一样,Zookeeper自己在处理协调的时候要复制多个主机。

ZooKeeper工作原理阐述(一)

Zookeeper服务的组成部分必须彼此都知道彼此,它们维持了一个内存状态影像,连同事务日志和快照在一个持久化的存储中。只要大多数的服务器是可用的,Zookeeper服务就是可用的。

客户端连接到一个单独的服务。客户端保持了一个TCP连接,通过这个TCP连接发送请求、获取响应、获取watch事件、和发送心跳。如果这个连接断了,会自动连接到其他不同的服务器。

3)序列

Zookeeper用数字标记每一个更新,用它来反射出所有的事务顺序。随后的操作可以使用这个顺序去实现更高级的抽象,例如同步原件。

4)快速

它在”Read-dominant”工作负载中特别快。Zookeeper 应用运行在数以千计的机器上,并且它通常在读比写多的时候运行的最好,读写大概比例在10:1。

 ZooKeeper的特性?

Zookeeper是非常简单和高效的。因为它的目标就是,作为建设复杂服务的基础,比如同步。zookeeper提供了一套保证,他们包括:

• 最终一致性:client不论连接到那个Server,展示给它的都是同一个视图。

• 可靠性:具有简单、健壮、良好的性能、如果消息m被到一台服务器接收,那么消息m将被所有服务器接收。

• 实时性:Zookeeper保证客户端将在一个时间间隔范围内获得服务器的更新信息,或者服务器失效的信息。但由于网络延时等原因,Zookeeper不能保证两个客户端能同时得到刚更新的数据,如果需要最新数据,应该在读数据之前调用sync()接口。

• 等待无关(wait-free):慢的或者失效的client不得干预快速的client的请求,使得每个client都能有效的等待。

• 原子性:更新只能成功或者失败,没有中间状态。

• 顺序性:包括全局有序和偏序两种:全局有序是指如果在一台服务器上消息a在消息b前发布,则在所有Server上消息a都将在消息b前被发布;偏序是指如果一个消息b在消息a后被同一个发送者发布,a必将排在b前面。

Zookeeper的工作原理

1)实现方式

Zookeeper Compnents 展示了Zookeeper服务的高级组件。除了请求处理器的异常之外,组成Zookeeper服务的服务器都会复制它们自己组件的副本。

ZooKeeper工作原理阐述(一)

Replicated database 是一个内存数据库,它包含全部的数据树。为了可恢复性,更新记录保存到磁盘上,并且写入操作在应用到内存数据库之前被序列化到磁盘上。

每个Zookeeper 服务端服务客户端。客户端正确的连接到一个服务器提交请求。每个服务端数据库的本地副本为读请求提供服务。服务的变化状态请求、写请求,被一个协议保护。

作为协议的一部分,所有的写操作从客户端转递到一台单独服务器,称为leader。其他的Zookeeper服务器叫做follows,它接收来自leader的消息建议并达成一致的消息建议。消息管理层负责在失败的时候更换Leader并同步Follows。

Zookeeper使用了一个自定义的原子消息协议。因为消息层是原子的,Zookeeper可以保证本地副本从不出现偏差。当leader接受到一个写请求,它计算写操作被应用时系统的状态,并将捕获到的新状态转化进入事务。

2)集群角色和状态

角色(3种):leader,follower,observer。

状态(4种):leading,following,observing,looking。

Zookeeper的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协议(ZooKeeper Atomic Broadcast protocol)。Zab协议有两种模式,它们分别是恢复模式(Recovery选主)和广播模式(Broadcast同步)。当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和leader的状态同步以后,恢复模式就结束了。状态同步保证了leader和Server具有相同的系统状态。

为了保证事务的顺序一致性,zookeeper采用了递增的事务id号(zxid)来标识事务。所有的提议(proposal)都在被提出的时候加上了zxid。实现中zxid是一个64位的数字,它高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch,标识当前属于那个leader的统治时期。低32位用于递增计数。

每个Server在工作过程中有4种状态:

LOOKING:当前Server不知道leader是谁,正在搜寻。

LEADING:当前Server即为选举出来的leader。

FOLLOWING:leader已经选举出来,当前Server与之同步。

OBSERVING:observer的行为在大多数情况下与follower完全一致,但是他们不参加选举和投票,而仅仅接受(observing)选举和投票的结果。

3)集群节点

Zookeeper节点部署越多,服务的可靠性越高,建议部署奇数个节点,因为zookeeper集群是以宕机个数过半才会让整个集群宕机的。

需要给每个zookeeper 1G左右的内存,如果可能的话,最好有独立的磁盘,因为独立磁盘可以确保zookeeper是高性能的。如果你的集群负载很重,要把zookeeper和RegionServer运行在同一台机器上面,就像DataNodes和TaskTrackers一样。

4)数据模型和分层的命名空间

Zookeeper提供的命名空间非常像一个标准的文件系统。一个名字是一系列的以’/’隔开的一个路径元素。Zookeeper命名空间中所有的节点都是通过路径识别。

ZooKeeper工作原理阐述(一)

不像标准的文件系统,Zookeeper命名空间中的每个节点可以有数据也可以有子目录。它就像一个既可以是文件也可以是目录的文件系统。(Zookeeper被设计成保存协调数据:状态信息,配置,位置信息,等等,所以每个节点存储的数据通常较小,通常在1个字节到数千字节的范围之内)。我们使用术语znode来表明Zookeeper的数据节点。

Znodes

Zookeeper中的每个节点都被称为Znode。Znode维护了一个stat结构,这个stat包含数据变化的版本号、访问控制列表变化。stat结构还有时间戳。版本号和时间戳一起,可让Zookeeper验证缓存和协调更新。每次znode的数据发生了变化,版本号就增加。例如,无论何时客户端检索数据,它也一起检索数据的版本号。并且当客户端执行更新或删除时,客户端必须提供他正在改变的znode的版本号。如果它提供的版本号和真实的数据版本号不一致,更新将会失败。(这种行为可以被覆盖)。命名空间中每个znode存储的数据自动的读取和写入的,读取时获得znode所有关联的数据字节,写入时替换所有的数据。每个节点都有一个访问控制列表来制约谁可以做什么。

在分布式应用工程中,node可以指的是一般的主机,一个服务器,全体成员的一员,一个客户端程序,等等。在Zookeeper的文档中,znode指的是数据节点。Servers指的是组成Zookeeper服务的机器;quorum peers指的是组成全体的servers;client指的是任何使用Zookeeper服务的主机和程序。

客户端可以在znode上设置watches。znode的变化将会触发watches后清除watches。触发watches时,Zookeeper向客户端发送一个通知。更多关于watches的信息可以在 Zookeeper watches 章节查看。

命名空间里的每个znodes上的数据存储都是原子性的读取和写入。读取时获取所有与znode有关的数据字节,写入时替换所有的数据字节。每个节点有一个访问控制列表用来限制谁可以做什么。

Zookeeper不是设计成通用的数据库或者大数据对象存储。而是管理协调数据。这个数据的形式是配置表单,状态信息,集合点等等。各种形式的协调数据属性都非常小:经过测量在KB之内。Zookeeper客户端和服务端实现检查确保znode有不到1M的数据,但是实际的数据要远小于平均值。在相对较大的数据上的操作将会引起一些操作花费更多的时间并且影响一些操作的延迟,因为需要额外的时间在网络和存储设备之间移动数据。如果需要大数据存储,通常的做法是将数据存储进大存储器系统,如NFS和HDFS,然后将存储指针和地址存储进Zookeeper。

Zookeeper还有一个临时节点的概念。这些znode一旦session创建就存在,session结束就被删除。因为这个特性,临时节点不允许有子节点。

Zookeeper被设计成高性能的。但真的是这样吗?Yahoo的Zookeeper开发团队的结果表明了它就是这样的。它在应用中读比写多的时候有特别高的性能,因为在写的时候包含所有服务器状态同步。(读比写多是协调服务的典型案例)

ZooKeeper工作原理阐述(一)

上图是Zookeeper3.2版本在dual 2Ghz Xeon and two SATA 15K RPM 驱动配置的服务器上的吞吐量图像。一个驱动作为专门的Zookeeper日志装置。快照写进操作系统驱动。1k的写请求和1K的读取请求。”Servers” 表明了Zookeeper全体的大小,组成Zookeeper服务的服务器数量。接近于30台机器模仿客户端。Zookeeper全体被配置为leaders不允许客户端连接。

测试基准也表明它是可靠的。Reliability in the Presence of Errors 展示了怎样部署应对各种失败。事件标记出以下几点:

1、一个follower的故障和恢复。

2、不同的follower的故障和恢复。

3、leader的故障。

4、两个followers的故障和恢复。

5、另一个leader的故障。

6)可靠性

展示我们启动了7台机器组成的Zookeeper服务注入超时故障的行为。我们之前运行了相同的饱和基准,但现在我们保持写的百分比在不变的30%,这是一个比较保守的工作负载比。

ZooKeeper工作原理阐述(一)

从这张图有几个重要的观察。第一,如果follows失败并快速的恢复,Zookeeper能够维持一个高的吞吐量尽管有故障。但也许更重要的是,leader选举算法允许系统快速恢复,足以预防吞吐量大幅下降。在我们的观测中,Zookeeper用了不到200ms的时间就选出了一个新的leader。第三,随着follower恢复,Zookeeper一旦开始处理它们的请求,它能够再次提高吞吐量。

Zookeeper的设计目标的其中之一就是提供一个简单的程序接口。因此,它只支持这些操作:

  • create – 在树形结构的位置中创建节点。
  • delete – 删除一个节点。
  • exists – 测试节点在指定位置上是否存在。
  • get data – 从节点上读取数据。
  • set data – 往节点写入输入。
  • get chilren – 检索一个节点的子节点列表。
  • sync – 等待传输数据。

如果您觉得本站对你有帮助,那么可以支付宝扫码捐助以帮助本站更好地发展,在此谢过。
喜欢 (3)
[资助本站您就扫码 谢谢]
分享 (0)

您必须 登录 才能发表评论!