首先认识ZooKeeper
ZooKeeper—译名为“动物园管理员”。动物园里当然有好多的动物,游客可以根据动物园提供的向导图到不同的场馆观赏各种类型的动物,而不是像走在原始丛林里,心惊胆颤的被动物所观赏。为了让各种不同的动物呆在它们应该呆的地方,而不是相互串门,或是相互厮杀,就需要动物园管理员按照动物的各种习性加以分类和管理,这样我们才能更加放心安全的观赏动物。
回到企业级应用系统中,随着信息化水平的不断提高,企业级系统变得越来越庞大臃肿,性能急剧下降,客户抱怨频频。拆分系统是目前我们可选择的解决系统可伸缩性和性能问题的唯一行之有效的方法。但是拆分系统同时也带来了系统的复杂性——各子系统不是孤立存在的,它们彼此之间需要协作和交互,这就是我们常说的分布式系统。各个子系统就好比动物园里的动物,为了使各个子系统能正常为用户提供统一的服务,必须需要一种机制来进行协调——这就是ZooKeeper(动物园管理员)。
为什么使用ZooKeeper
我们知道要写一个分布式应用是非常困难的,主要原因就是局部故障。一个消息通过网络在两个节点之间传递时,网络如果发生故障,发送方并不知道接收方是否接收到了这个消息。他可能在网络故障迁就收到了此消息,也可能没有收到,又或者可能接收方的进程死了。发送方了解情况的唯一方法就是再次连接发送方,并向他进行询问。这就是局部故障:根本不知道操作是否失败。因此,大部分分布式应用需要一个主控、协调控制器来管理物理分布的子进程。目前,大部分应用需要开发私有的协调程序,缺乏一个通用的机制。协调程序的反复编写浪费,且难以形成通用、伸缩性好的协调器。协调服务非常容易出错,并很难从故障中恢复。例如:协调服务很容易处于竞态1甚至死锁2。Zookeeper的设计目的,是为了减轻分布式应用程序所承担的协调任务。
Zookeeper并不能阻止局部故障的发生,因为它们的本质是分布式系统。他当然也不会隐藏局部故障。ZooKeeper的目的就是提供一些工具集,用来建立安全处理局部故障的分布式应用。
ZooKeeper是一个分布式小文件系统,并且被设计为高可用性。通过选举算法和集群复制可以避免单点故障,由于是文件系统,所以即使所有的ZooKeeper节点全部挂掉,数据也不会丢失,重启服务器之后,数据即可恢复。另外ZooKeeper的节点更新是原子的,也就是说更新不是成功就是失败。通过版本号,ZooKeeper实现了更新的乐观锁,当版本号不相符时,则表示待更新的节点已经被其他客户端提前更新了,而当前的整个更新操作将全部失败。当然所有的一切ZooKeeper已经为开发者提供了保障,我们需要做的只是调用API。与此同时,随着分布式应用的的不断深入,需要对集群管理逐步透明化监控集群和作业状态,可以充分利ZK的独有特性。
ZooKeeper的应用
ZooKeeper本质上是一个分布式的小文件存储系统。原本是ApacheHadoop的一个组件,现在被拆分为一个Hadoop的独立子项目,在Hbase(Hadoop的另外一个被拆分出来的子项目,用于分布式环境下的超大数据量的DBMS)中也用到了ZooKeeper集群。
Hadoop,使用Zookeeper的事件处理确保整个集群只有一个NameNode,存储配置信息等.HBase,使用Zookeeper的事件处理确保整个集群只有一个HMaster,察觉HRegionServer联机和宕(dàng)机,存储访问控制列表等。
有人会怀疑ZooKeeper的执行能力,在ZooKeeper诞生的地方——Yahoo!他被用作雅虎消息代理的协调和故障恢复服务。雅虎消息代理是一个高度可扩展的发布-订阅系统,他管理着成千上万台联及程序和信息控制系统。它的吞吐量标准已经达到大约每秒基于写操作的工作量。对于读操作的工作量来说,它的吞吐量标准还要高几倍。
ZooKeeper的概述
Zookeeper是为分布式应用程序提供高性能协调服务的工具集合,也是Google的Chubby一个开源的实现,是Hadoop的分布式协调服务。它包含一个简单的原语集,分布式应用程序可以基于它实现配置维护、命名服务、分布式同步、组服务等。Zookeeper可以用来保证数据在ZK集群之间的数据的事务性一致。其中ZooKeeper提供通用的分布式锁服务,用以协调分布式应用。
Zookeeper作为Hadoop项目中的一个子项目,是Hadoop集群管理的一个必不可少的模块,它主要用来解决分布式应用中经常遇到的数据管理问题,如集群管理、统一命名服务、分布式配置管理、分布式消息队列、分布式锁、分布式协调等。在Hadoop中,它管理Hadoop集群中的NameNode,还有在Hbase中MasterElection、Server之间状态同状步等。Zoopkeeper提供了一套很好的分布式集群管理的机制,就是它这种基于层次型的目录树的数据结构,并对树中的节点进行有效管理,从而可以设计出多种多样的分布式的数据管理模型。
Zookeeper是ApacheHadoop的一个子项目,主要是用来解决分布式应用中经常遇到的一些数据管理问题。下图列举了一些可能会遇到的场景:
ZooKeeper的设计目标
众所周知,分布式环境下的程序和活动为了达到协调一致目的,通常具有某些共同的特点,例如,简单性、有序性等。ZooKeeper不但在这些目标的实现上有自身特点,并且具有独特优势。高性能保证了ZooKeeper可以用于大型的分布式系统,高可靠保证了ZooKeeper不会发生单点故障,严格的顺序访问保证了客户端可以获得复杂的同步操作原语。下面我们将简述ZooKeeper的设计目标。
(1)数据结构简单
ZooKeeper允许各分布式进程通过一个共享的命名空间相互联系,该命名空间类似于一个标准的层次型的文件系统:由若干注册了的数据节点构成(用Zookeeper的术语叫znode),这些节点类似于文件和目录。典型的文件系统是基于存储设备的,传统的文件系统主要用于存储功能,然而ZooKepper的数据是保存在内存中的。也就是说,可以获得高吞吐和低延迟。ZooKeeper的实现非常重视高性能、高可靠,以及严格的有序访问。
(2)高可靠(健壮性)
就像ZooKeeper需要协调的分布式系统一样,它本身就是具有冗余结构,它构建在一系列主机之上,叫做一个”ensemble”。构成ZooKeeper服务的各服务器之间必须相互知道,它们维护着一个状态信息的内存映像,以及在持久化存储中维护着事务日志和快照。只要大部分服务器正常工作,ZooKeeper服务就能正常工作。客户端连接到一台ZooKeeper服务器。客户端维护这个TCP连接,通过这个连接,客户端可以发送请求、得到应答,得到监视事件以及发送心跳。如果这个连接断了,客户端可以连接到另一个ZooKeeper服务器。
(3)有序性(严格的顺序访问)
ZooKeeper给每次更新附加一个数字标签,表明ZooKeeper中的事务顺序,后续操作可以利用这个顺序来完成更高层次的抽象功能,例如同步原语7。
(4)高性能(速度优势)
ZooKeeper特别适合于以读为主要负荷的场合。ZooKeeper可以运行在数千台机器上,如果大部分操作为读,例如读写比例为10:1,ZooKeeper的效率会很高。
ZooKeeper的集群
ZK集群如下图2.1所示。这是实际应用的一个场景,该ZooKeeper集群当中一共有5台服务器,有两种角色Leader和Follwer,5台服务器连通在一起,客户端有分别连在不同的ZK服务器上。如果当数据通过客户端1,在左边第一台Follower服务器上做了一次数据变更,他会把这个数据的变化同步到其他所有的服务器,同步结束之后,那么其他的客户端都会获得这个数据的变化。
图2.1
注意:
通常Zookeeper由2n+1台servers组成,每个server都知道彼此的存在。每个server都维护的内存状态镜像以及持久化存储的事务日志和快照。为了保证Leader选举能过得到多数的支持,所以ZooKeeper集群的数量一般为奇数。对于2n+1台server,只要有n+1台(大多数)server可用,整个系统保持可用。所以Zookeeper集群至少需要3台servers服务器!
集群中的角色
在ZooKeeper集群当中,集群中的服务器角色有两种Leader和Learner,Learner角色又分为Observer和Follower,具体功能如下:
Leader(领导者)为客户端提供读和写的服务,负责投票的发起和决议,更新系统状态。
Follower(跟随者)为客户端提供读服务,如果是写服务则转发给Leader。在选举过程中参与投票。
Observe(观察者)为客户端提供读服务器,如果是写服务则转发给Leader。不参与选举过程中的投票,也不参与“过半写成功”策略。在不影响写性能的情况下提升集群的读性能。此角色于zookeeper3.3系列新增的角色。
client(客户端)连接zookeeper服务器的使用着,请求的发起者。独立于zookeeper服务器集群之外的角色。
领导者(leader),负责进行投票的发起和决议,更新系统状态
学习者(learner),包括跟随者(follower)和观察者(observer),
客户端(client),请求发起方
下面通过一张图系统架构图了解一下各个角色所处的位置。
ZooKeeper的组件图中给出了ZooKeeper服务的高层次的组件。除了请求处理器(requestprocessor)外,构成ZooKeeper服务的每个服务器都有一个备份。复制的数据库(Replicateddatabase)是一个内存数据库,包含整个数据树。为了可恢复,更新会被log到磁盘,并且在更新这个内存数据库之前,先序列化到磁盘。
每个ZooKeeper都为客户端提供服务。客户端只连接到一个服务器,并提交请求。读请求直接由本地的复制数据库提供数据。对服务状态进行修改的请求、写请求通过一个约定的协议进行通讯。
作为这个协议的一部分,所有的写请求都被传送到一个叫“首领(leader)”的服务器,而其他的服务器,叫做“(随从)followers”,follower从leader接收信息修改的提议,并同意进行。当leader发生故障时,协议的信息层(messaginglayer)