Zookeeper概述
Zookeeper是一个开放源码的分布式应用程序协调服务,是 Google的Chubby一个开源的实现,是 Hadoop和 HBASE的重要组件。主要解决分布式应用一致性问题。
1.分布式应用
分布式应用可以在给定时间(同时)在网络中的多个系统上运行,通过协调它们以快速有效的方式完成特定任务。通常来说,对于复杂而耗时的任务,非分布式应用(运行在单个系统中)需要几个小时才能完成,而分布式应用通过使用所有系统涉及的计算能力可以在几分钟内完成。
通过将分布式应用配置为在更多系统上运行,可以进一步减少完成任务的时间。分布式应用正在运行的一组系统称为集群,而在集群中运行的每台机器被称为节点。
分布式应用有两部分, Server(服务器) 和 Client(客户端) 应用程序。服务器应用程序实际上是分布式的,并具有通用接口,以便客户端可以连接到集群中的任何服务器并获得相同的结果。 客户端应用程序是与分布式应用进行交互的工具。
分布式应用的优点
- 可靠性 - 单个或几个系统的故障不会使整个系统出现故障。
- 可扩展性 - 可以在需要时增加性能,通过添加更多机器,在应用程序配置中进行微小的更改,而不会有停机时间。
- 透明性 - 隐藏系统的复杂性,并将其显示为单个实体/应用程序。
分布式应用的挑战
- 竞争条件 - 两个或多个机器尝试执行特定任务,实际上只需在任意给定时间由单个机器完成。例如,共享资源只能在任意给定时间由单个机器修改。
- 死锁 - 两个或多个操作等待彼此无限期完成。
- 不一致 - 数据的部分失败。
分布式应用程序提供了很多好处,但它们也抛出了一些复杂和难以解决的挑战。ZooKeeper框架提供了一个完整的机制来克服所有的挑战。
2. Zookeeper简介
Zookeeper是一个能够高效开发和维护分布式的开放源码的应用协调服务。是Google的 Chubby一个开源的实现,是 Hadoop和 HBASE的重要组件。Zookeeper是一个为分布式应用提供一致性服务的软件,提供的功能包括维护配置信息、名字服务、分布式同步、组服务等。ZooKeeper框架最初是在“Yahoo!"上构建的,用于以简单而稳健的方式访问他们的应用程序。 后来,Apache ZooKeeper成为Hadoop,HBase和其他分布式框架使用的有组织服务的标准。
首先我们对上一个段落做一个解释。
- Zookeeper是一个开放源代码的软件。
- Zookeeper是一个管理“分布式应用程序”的软件。什么是分布式应用程序服务?我们知道,Hadoop中的组件,如hdfs、MapReduce/yarn、hbase、double、kafka都是分布式服务。如MapReduce就是一个分布式服务,MapReduce会将所做的工作分发给Hadoop集群中的多台服务器共同实现。如何对分布式服务做协调,管理这些运行在不同电脑上的任务?就需要一个对分布式应用程序做协调的服务,这就是Zookeeper的工作。
- Zookeeper可以实现对分布式应用程序做一致性服务,什么是一致性服务?比如我们对A服务器上的一个数据进行了修改,这个数据同时在D服务器和M服务器有两个备份,这时就要对D服务器和M服务器有两个备份都进行修改,这就是一致性服务。Zookeeper就可以实现这么一个一致性服务。
- Zookeeper实现的强一致性服务。一致性服务分为3类,分别是:
- 强一致性:a发生变化,b立刻就发生变化
- 弱一致性:a发生变化,b过一会会发生变化
- 最终一致性:a发生变化,b最终也会发生变化
Zookeeper可以实现立刻的数据一致性,即强一致性。
大家知道,Hadoop生态系统中的组件,都喜欢起动物的名称。如Hadoop、Hive、Pig等。而Zookeeper中文意思是动物园管理员,就是管理Hadoop生态系统。
5. ZooKeeper的好处
以下是使用ZooKeeper的好处:
- 简单的分布式协调过程
- 同步 - 服务器进程之间的相互排斥和协作。此过程有助于Apache HBase进行配置管理。
- 有序的消息
- 序列化 - 根据特定规则对数据进行编码。确保应用程序运行一致。这种方法可以在MapReduce中用来协调队列以执行运行的线程。
- 可靠性
- 原子性 - 数据转移完全成功或完全失败,但没有事务是部分的。
3 .Zookeeper的选举机制
看看下面的图表。它描述了ZooKeeper的“客户端-服务器架构”。
配置多个实例共同构成一个Zookeeper集群对外提供服务以达到水平扩展的目的,集群中的每一台电脑都称为服务器(Server),每个服务器上的数据是相同的,每一个服务器均可以对外提供读和写的服务,这点和redis是相同的,即对客户端来讲每个服务器都是平等的。zookeeper集群一般需要奇数台服务器,为什么是奇数台服务器?因为我们需要通过选举机制选出领导者(leader),所以必须是奇数台服务器。
Zookeeper提供了三种选举机制:
- LeaderElection
- AuthFastLeaderElection
- FastLeaderElection
默认的算法是FastLeaderElection,所以这篇主要分析它的选举机制。
客户端(client)是请求发起方。服务器分为不同的角色,有领导者(leader),也有学习者(learner)。角色的不同是在选举中产生的,下面是选举的流程。
目前有5台服务器,每台服务器均没有数据,它们的编号分别是A,B,C,D,E按编号依次启动,它们的选择举过程如下:
- 服务器A启动,给自己投票,然后发投票信息,由于其它机器还没有启动所以它收不到反馈信息,服务器A的状态一直属于Looking(选举状态)。
- 服务器B启动,给自己投票,同时与之前启动的服务器A交换结果,由于服务器B的编号大所以服务器B胜出,但此时投票数没有大于半数,所以两个服务器的状态依然是Looking(选举状态)。
- 服务器C启动,给自己投票,同时与之前启动的服务器A,B交换信息,由于服务器C的编号最大所以服务器C胜出,此时投票数正好大于半数,所以服务器C成为领导者(Leader),服务器A,B成为小弟。
- 服务器D启动,给自己投票,同时与之前启动的服务器A,B,C交换信息,尽管服务器D的编号大,但之前服务器C已经胜出,所以服务器D只能成为小弟。
- 服务器E启动,后面的逻辑同服务器E成为小弟。
这里的小弟就是学习者(learner)。学习者(learner)分为两类,能够参与投票的就是跟随者(follower),否则就是观察者(observer)。
服务器有以下状态。
- LOOKING:竞选状态。
- FOLLOWING:随从状态,同步leader状态,参与投票。
- OBSERVING:观察状态,同步leader状态,不参与投票。
- LEADING:领导者状态。
下面是选举的简易流程图。
以下是选举状态图
描述Leader选择过程中的状态变化,这是假设全部实例中均没有数据,假设服务器启动顺序分别为:A,B,C。
角色 |
描述 |
||
服务器(Server) |
领导者(Leader) |
服务器节点,负责进行投票的发起和决议,更新系统状态。 |
|
学习者(Learner) |
跟随者(Follower) |
服务器节点,用于接收客户端请求并向客户端返回结果,在选举过程中能参与投票。 |
|
观察者(Observer) |
当集群节点数目逐渐增大为了支持更多的客户端,需要增加更多Server,然而Server增多,投票阶段延迟增大,影响性能。为了权衡伸缩性和高吞吐率,引入Observer。 服务器节点,可以接收客户端连接,将写请求转发给Leader节点。但Observer不能参与投票,只同步Leader的状态。Observer的目的是为了扩展系统,提高读取速度。 |
||
客户端(Client) |
请求发起方 |
4. Zookeeper的读写机制
Zookeeper是分布式应用程序的协调程序。分布式应用程序运行在集群上,客户端对一台服务器的请求完成后修改了数据并将数据同步到其他备份,并且需要将结果告知集群中所有电脑,这个由分布式应用程序自身实现吗?可以,但是也可以由另一个协调程序完成这个功能,Zookeeper就是这么一个协调程序。下面我们介绍以下Zookeeper写流程。下面我们见下图。
客户端首先和一个Server或者Observer(可以认为是一个Server的代理)通信,发起写请求,然后Server将写请求转发给Leader,Leader再将写请求转发给其他Server,Server在接收到写请求后写入数据并回应Leader,Leader在接收到大多数写成功回应后,认为数据写成功,回应Client。
|
Zookeeper读取由特定连接的Server在内部执行,因此不需要与集群进行交互。
5. Zookeeper的数据模型
Zookeeper的数据保存在一个类似于文件系统的一个树形结构中,每个数据节点只能携带少量的数据。为什么只能携带少量的数据呢?因为Zookeeper用于进行协调服务的,所以不需要携带大量数据。
每个数据节点(树中的每一个分支节点或者叶子节点)称之为znode。每一个znode节点既是目录又是文件(是文件的含义是它可以带少量数据,是目录的含义是它有可能还有子目录),这和我们普通看到的文件系统不一样。
每个目录在zookeeper中叫做znode,并且其有一个唯一的路径标识,如/services/myservice/servers/stuidname1
- znode有两种类型,短暂的(ephemeral: 断开连接自己删除)和持久的(ersistent: 断开连接不删除);
- znode可以包含数据和子znode(ephemeral类型的节点不能有子znode);
- znode中的数据可以有多个版本,比如某一个znode下存有多个数据版本,那么查询这个路径下的数据需带上版本;
创建znode时设置顺序标识,znode名称后会附加一个值,顺序号是一个单调递增的计数器,由父节点维护 。
如存一个/stu/name值mike,会对路径上加序列化,如/name000001
再存一个/stu/name值jack,会对路径上加序列化, 如/name000002
上面的znode就有两个版本
- 客户端应用可以在znode上设置监视器(Watcher)。
- znode不支持部分读写,而是一次性完整读写
- znode的类型在创建时确定并且之后不能再修改;
- ephemeral znode的客户端会话结束时,zookeeper会将该ephemeral znode删除,ephemeral znode不可以有子节点;
- persistent znode不依赖于客户端会话,只有当客户端明确要删除该persistent znode时才会被删除;
Zookeeper以节点的方式存储一些关键信息,默认情况下,所有应用都可以读写任何节点,在复杂的应用中,这不太安全,Zookeeper通过ACL(Access Controll List)机制来解决访问权限问题。
总体来说,Zookeeper的节点有5种ACL(Access Controller List)权限:
- CREATE 允许创建Child Nodes
- READ 允许获取ZNode的数据,以及该节点的孩子列表
- WRITE 可以修改ZNode的数据
- DELETE 可以删除一个孩子节点
- ADMIN 可以设置权限
这5种权限简写为crwda(即:每个单词的首字符缩写)。注意这5种权限中,delete是指对子节点的删除权限,其它4种权限指对自身节点的操作权限。
6. Zookeeper的监听机制
Zookeeper的节点是可以被监控,目录中存储数据的修改、子节点目录的变化,都可以触发事件并通知监听的客户端,这是 Zookeeper重要的特性。通过此特性可以实现的功能个监听事件是一个有配置的集中管理、集群管理、分布式锁等。监听机制官方说明为次性的监听器,当被设置了监听的数据发生变化时,服务器就会将这个改变发送给负责设置 Watch的客户端。
ZooKeeper中的Watch是只能触发一次。也就是说,如果客户端在指定的ZNode设置了Watch,如果该ZNode数据发生变更,ZooKeeper会发送一个变更通知给客户端,同时触发设置的Watch事件。如果ZNode数据又发生了变更,客户端在收到第一次通知后没有重新设置该ZNode的Watch,则ZooKeeper就不会发送一个变更通知给客户端。
Zookeeper的特点是
- 一次性触发
- 事件触发后发给客户端。
- 数据被设置 Watch