学习目标

了解ZooKeper的特性,能够简述ZooKeper的5个特性。

●

● 掌握ZooKeper的集群架构,能够描述ZooKeper集群中Leader、Folower和
Observer的作用。
● 熟悉ZooKeper的数据模型,能够描述ZooKeper中3种ZNode类型的作用。
● 熟悉ZooKeper的Watcher机制,能够描述事件监听机制的特性。
● 熟悉ZooKeper的选举机制,能够描述ZooKeper集群选举Leader的两种情况及其
过程。
● 掌握完全分布式模式部署ZooKeper集群,能够独立完成基于完全分布式模式部署
ZooKeper集群。
● 了解伪分布式模式部署ZooKeper集群,能够完成基于伪分布式模式部署ZooKeper 
集群。
● 掌握Zr的Shl 
操作,能够熟练使用客户端工具zi对Zr集群进行
操作。
ooKepeekClooKepe
● 掌握ZooKeper的JavaAPI操作,能够熟练使用ZooKeper提供的JavaAPI对
ZooKeper进行操作。
ZooKeper是一个开源的分布式协调服务,它是GoogleChubby的开源实现,设计目标是
将那些复杂且容易出错的分布式应用封装起来,以构成一个高效可靠的原语集,并以一系列简
单易用的接口提供给用户使用。本章将针对ZooKeper的基础知识和常见操作进行详细
讲解。

5.1 
ZooKeper简介
ZooKeper最早起源于某研究院的一个研究小组。当时,研究人员发现很多分布式应用
基本都需要依赖一个类似的应用进行分布式协调,但是这些分布式应用往往都存在分布式单
点问题,即在整个分布式应用中,如果某个独立功能的程序或角色只运行在某一台服务器上, 
那么这个结点就称为单点,一旦这台服务器宕机,那么整个分布式应用都将无法正常运行,这
种现象就称为单点问题。所以,研究人员试图开发一个通用的无单点问题的分布式协调服务, 
以便让研究人员将精力集中在业务逻辑上,此时,ZooKeper便应运而生。


132 
Hadoop大数据技术原理与应用(第2版) 

5.1.1 
ZooKeeper特性
ZooKeper是一个开源的分布式协调服务,它为分布式应用提供了高效且可靠的分布式
协调服务,并且是分布式应用保证数据一致性的解决方案。分布式应用可以基于ZooKeper 
实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master选举、分
布式锁、分布式队列等功能。ZooKer之所以能够确保分布式应用的数据一致,离不开它的
5个特性,具体介绍如下。
ep

1.顺序一致性
顺序一致性(SequentialConsistency)是指对于客户端发起的每个事务请求,ZooKeper 
都会为其分配一个全局唯一的递增编号,这个编号反映了所有事务请求的先后顺序, 
ZooKeper会严格按照事务请求的顺序进行处理。

2.原子性
原子性(Atomicity)是指事务请求的处理结果在整个集群中的应用情况是一致的,也就是
说,要么集群中的所有服务器成功地将事务请求应用到ZooKeper,要么整个集群中的所有服
务器都没有将事务请求应用到ZooKeper。

3.可靠性
可靠性(Reliability)是指一旦ZooKeper应用了客户端的某个事务请求,并且将该事务请
求的处理结果响应给客户端,那么该事务请求引起的ZooKeper数据的变更就会被一直保
留,除非其他事务请求对其进行了变更。

4.单一系统映像
单一系统映像(SingleSystemImage)是指无论客户端连接集群中的哪个ZooKeper,看
到的数据都是一致的。

5.时效性
时效性(Timelines)是指当客户端发送的事务请求成功应用到ZooKeper之后, 
ZooKeper可以确保在一定时间内,其他客户端能够读取该事务请求对数据进行变更的结果, 
而不是立即读取该事务请求对数据进行变更的结果,因此时效性较低。


多学一招:事务请求和非事务请求

在ZooKeper中,客户端向ZooKeper发起的请求分为事务请求和非事务请求,其中, 
务请求会使ZooKeper的数据发生变更,例如写入、修改、删除等;非事务操作仅仅读取(事) ZooKeper的数据,并不会使ZooKeper的数据发生变更。

5.2 
Zoeper集群架构
1.oKe

ZooKeper集群由多个服务器组成,每个服务器在ZooKeper集群中扮演着不同的角色, 
包括Leader、Folower和Observer,如图5-1所示。
接下来对图5-1展示的ZooKeper集群中的3个角色进行详细介绍。

1.Leader 

Leader是ZooKeper集群的核心,每个ZooKeper集群中只能有一个Leader,主要用于
处理客户端发送的事务请求,并将事务请求广播到所有Folower,以保证处理事务请求的顺序


第5章ZooKeper分布式协调服务133 


图5-
1 
ZoKeper集群架构

一致性。同时,为了确保Folower可以检测到Leader的存在,Leader会与Folower同步状
态信息。

2.Folower 

Folower可以看作Leader的跟随者,每个ZooKeper集群中可以包含多个Folower,它
的作用主要有以下4点。

● 处理客户端发送的非事务请求。
● 将客户端发送的事务请求转发给Leader。
● 参与事务请求投票,即每个Folower成功应用Leader广播的事务请求后,将向Leader 
发送反馈信息,如果超过半数的Folower向Leader发送了反馈信息,则认为该事务请
求应用到了整个ZooKeper集群。
● 参与Leader选举投票,如果当前Leader宕机,则所有Folower会重新投票选举出一个
新的Leader。
3.Observer 

Observer可以看作Leader的观察者,每个ZooKeper集群中可以包含多个Observer,主
要负责同步Leader的数据,处理客户端发送的非事务请求,并将事务请求转发给Leader,通常
用于在不影响集群事务请求处理能力的前提下,提升集群的非事务请求处理能力。需要注意
的是,Observer不参与任何形式的投票,如Leader选举投票。

在ZooKeper集群中,每个服务器扮演着不同的角色,就像一个团队中的每个成员也扮
演着不同的角色。只有ZooKeper集群中的每个服务器都履行好自己的职责,才能实现高可
用和高可靠。类似地,在一个团队中,每个成员只有履行好自己的职责,才能为团队的成功做
出贡献。

5.oKer数据模型
2 
Zoep

ZooKeper的视图结构和标准的UNIX文件系统非常类似,但没有引入UNIX文件系统
中目录和文件的相关概念,而是使用了其特有的“数据结点”概念,称为ZNode。ZNode是


134 
Hadoop大数据技术原理与应用(第2版) 

ZooKeper中数据的最小单元,每个ZNode默认能够保
存1MB的数据,同时可以挂载子结点,挂载的子结点也
可以单独看作ZNode,从而构成一个层次化的命名空间, 

称为树。ZooKeper数据模型如图5-2所示。

从图5-2可以看出,ZooKeper的数据模型由多个
ZNode组成,如“/”“/app1”“/app2”,每个ZNode都可以
挂载子结点,如“/”的子结点为“/app1”和“/app2”,这些
ZNode按层次化结构组织形成树状结构。ZNode的路径
标识方式和UNIX文件系统相似,都使用一系列斜杠(/)

图5-
2 
ZoKeper数据模型进行分割的路径表示。

在ZooKeper中,每个ZNode都是有生命周期的,其生命周期的长短取决于ZNode的类
型。ZNode的类型主要分为持久结点(PERSISTENT )、临时结点(EPHEMERAL)和顺序结
点(SEQUENTIAL )。

1.持久结点
持久结点是ZooKeper中最常见的一种ZNode类型,它的生命周期取决于用户何时进行
删除操作,持久结点被创建后,便会一直存在于ZooKeper中,除非主动删除持久结点。

2.临时结点
与持久结点有所不同,临时结点的生命周期取决于客户端会话。客户端会话是指客户端
与ZooKeper成功建立连接后创建的会话,若此时在ZooKeper中创建临时结点,则在客户
端与ZooKeper断开连接时,临时结点便会被自动清理。需要注意的是,临时结点不能挂载
子结点,只能存储数据。

3.顺序结点
顺序结点基于持久结点和临时结点创建,因此可以将顺序结点分为持久顺序结点和临时顺
序结点。在创建顺序结点时,默认会在顺序结点的基础上设置一个不断增加的序号,该序号对于
当前顺序结点的父结点来说是唯一的,这样便于记录父结点中每个子结点创建的先后顺序。

序号的格式由10位数字组成,起始序号为0000000000,例如在名称为/node的ZNode下
先后创建了3个顺序结点,那么这3个顺序结点的序号分别是0000000000 、000000001和
0000000002 。需要注意的是,持久结点和临时结点也会使序号增加,例如再次在/node下先创
建一个持久结点,再创建一个顺序结点,那么此时该顺序结点的序号为0000000004,而不是
0000000003 。值得一提的是,只有当在ZNode下创建了顺序结点之后,序号才会增加,如在同
一ZNode下先创建一个持久结点,再创建一个顺序结点,那么该顺序结点的序号为
0000000000,而不是0000000001 。

5.oKeper典型应用场景
3 
Zo

随着近年来互联网系统规模的不断扩大,大数据时代飞速到来,越来越多的分布式应用将
ZooKeper作为核心组件,如Hadoop、HBase和Kafka等,因此,正确理解ZooKeper的应用
场景,对于ZooKeper的使用者来说显得尤为重要。本节将重点围绕数据发布/订阅、命名服
务和分布式锁讲解ZooKeper的典型应用场景。


第5章ZooKeper分布式协调服务135 

1.数据发布/订阅
数据发布/订阅是指发布者将数据发布到ZoKeper的一个或一系列ZNode上,供订阅者进
行数据订阅,进而达到动态获取数据的目的,实现配置信息的集中式管理和数据的动态更新。

在数据发布/订阅中应用ZooKeper时,订阅者会向ZooKeper指定的ZNode注册一
个
Watcher进行监听,一旦该ZNode的数据发生变化,那么ZooKeper就会向相应的订阅者
发
送事件通知,当订阅者接收到这个通知后,便会主动到ZooKeper指定的ZNode中获取最
新
的数据
。


2.命名服务
命名服务也是分布式系统中比较常见的应用场景,它是分布式应用基础的公共服务之一
。
在分布式应用中,被命名的实体通常是集群中的服务器、提供服务的地址或远程对象等,这
些
实体统称为命名空间(NameSpace),其中,较为常见的是一些分布式服务框架(如RPC 、RMI)
中的服务地址列表,通过命名服务,客户端能够根据指定名字从ZooKeper获取资源的实体
、
服务地址和提供者等信息
。


3.分布式锁
分布式锁是控制分布式应用之间同步访问共享资源的一种方式。如果不同的应用或同一

应用的不同主机共享资源,那么访问这些资源时,往往需要通过一些互斥手段防止彼此之间的

干扰,以保证一致性,在这种情况下,就需要使用分布式锁。

分布式锁主要分为排他锁和共享锁,具体内容如下。

1)排他锁

排他锁(ExclusiveLocks,简称X锁)又称独占锁,ZooKeper实现排他锁时,通常的做法

是把ZNode看作一把锁,所有客户端都会试图在该ZNode下创建临时结点以获取这个锁,不

过最终只有一个客户端可以获取该锁,这是因为同一ZNode下的临时结点不能存在相同名

称,其他没有获取锁的客户端会在ZNode下注册一个Watcher实时监听临时结点的变化,当

获取锁的客户端正常执行完业务逻辑后,便会断开连接,此时该客户端创建的临时结点便会自

动删除,没有获取锁的客户端会重新试图在ZNode中创建临时目录以获取锁。

2)共享锁

共享锁(SharedLocks,简称S锁)又称读锁,ZooKeper在实现共享锁时,通常的做法是
把ZNode看作一把锁,所有客户端都会试图在该ZNode下创建类似于“/shared_lock/
[hostname]请求类型-序号”的临时顺序结点,所有客户端都会按照临时顺序结点创建的先后

-
顺序依次执行。例如/shrd_lc168.161R0000000001和/saed_ok/192.


aeok/192.121.--hrlc168. 

121.--0000000002分别表示读请求和写请求的临时顺序结点,其中,读请求的临时顺序
161W
结点先执行,写请求的临时顺序结点后执行
。


5.4 
ZooKeper的Watcher机制
ZooKeper在实现数据发布/订阅时,订阅者会在ZooKeper指定的ZNode上注册
Watcher进行监听,一旦该ZNode的数据发生变化,ZooKeper就会向相应的订阅者发送事件
通知,这一过程是通过ZooKeper的Watcher机制实现的。ZooKeper的Watcher机制允许
客户端向ZooKeper注册Watcher以监听指定事件,一旦Watcher监听的事件被触发, 


136 
Hadoop大数据技术原理与应用(第2版) 

ZooKeper便会向客户端发送一个事件通知。ZooKeper的Watcher机制依赖于以下几点特
性实现数据发布、订阅的功能。

1.一次性
一次性指的是Watcher监听的事件一旦被触发,那么该Watcher就会被移除,所以
Watcher需要反复注册才能使用。这样做的好处是可以有效减轻ZooKeper的压力。试想, 
如果注册的Watcher一直有效,那么针对那些更新比较频繁的ZNode,ZooKeper会不断向客
户端发送事件通知,这对于网络I/O以及ZooKeper性能的影响都非常大。

2.客户端串行执行
客户端Watcher回调的过程是一个串行同步的过程,客户端接收到ZooKeper发送的事
件通知时,会通过回调实现对事件的处理,并且所有Watcher的回调都不会并发执行,而是按
照回调顺序一个一个地执行。如果某个客户端Watcher回调的处理逻辑过于复杂,那么将影
响其他客户端的Watcher回调。

3.轻量级
WatchedEvent是Watcher机制的最小事件通知单元,它的数据结构中只包含三部分内
容,分别是通知状态、事件类型和结点路径。也就是说,ZooKeper发送的事件通知内容非常
简单,只会告诉客户端发生了事件,而不会说明事件的具体内容。例如,注册在ZooKeper的
Watcher监听某个ZNode时,如果ZNode的数据发生变化,那么ZooKeper发送的事件通知只会
告知客户端ZNode的数据发生了变化,而不是告知数据发生了什么变化。

ZooKeper发送的事件通知由通知状态、事件类型和结点路径组成,其中,结点路径就是
Watcher监听ZNode的路径,但不包含ZNode的数据;通知状态和事件类型用于标识
Watcher监听的事件,常见的通知状态和事件类型如表5-1所示。

表5-
1 
常见的通知状态和事件类型

通知状态事件类型事件
None 客户端与ZooKeper成功建立会话
NodeCreated Watcher监听的ZNode被创建
SyncConnected NodeDeleted Watcher监听的ZNode被删除
NodeDataChanged Watcher监听的ZNode的数据发生变化
NodeChildrenChanged Watcher监听的ZNode的子结点发生变化
Disconnected None 客户端与ZooKeper断开连接
Expired None 客户端与ZooKeper建立的会话连接超时

从表5-1可以看出,Watcher监听的每种事件都由不同通知状态和事件类型的组合进行
标识,例如通知状态SyncConnected和事件类型None的组合标识的事件为客户端与
ZooKeper成功建立会话。

5.oKer的选举机制
5 
Zoep

ZooKeper的选举机制是指从ZooKeper集群的多个服务器中选举出一个服务器作为
Leader。为了确保ZooKeper能够成功选举出Leader,ZooKeper集群的服务器数量要满足
2N+1(N为正整数),即ZooKeper集群最少需要3台服务器。ZooKeper触发选举机制的


第5章ZooKeper分布式协调服务137 

情况有两种,一种是启动ZooKeper集群时,通过触发选举机制选举Leader;另一种是
ZooKeper集群运行期间,如果Leader宕机,那么可以通过触发选举机制选举出新的Leader。
触发选举机制进行选举Leader的过程中,ZooKeper的myid和zxid会直接影响最终的
选举结果,关于myid和zxid的介绍如下。

●myid。myid可以称为服务器ID,它是用户在部署ZooKeper集群时,为每台服务器运
行的ZooKeper服务指定的编号,编号的值越大,ZooKeper服务被选举为Leader的
权重越高。需要注意的是,用户为每个ZooKeper服务指定的编号不能重复。
●zxid。zxid可以称为事务ID,它是一个Long型的64位整数,其中,低32位可以看作一
个简单的单调递增的计数器,用于记录ZooKeper服务处理事务请求的次数,每处理
一次事务请求,计数器便会加1;高32位表示时间戳,用于记录Leader周期的编号,每
当选举产生一个新的Leader时,便会将时间戳加1,并且重置计数器为0。例如,启动
ZooKeper集群时,在未选举出Leader之前,所有ZooKeper服务中zxid的时间戳都
是0,当选举出Leader之后,时间戳变为1,若在后续ZooKeper运行过程中Leader宕
机了,重新选举出新的Leader,那么此时除宕机的Leader之外,所有ZooKeper服务中
zxid的时间戳都会变为2。
了解myid和zxid的概念之后,下面分别介绍ZooKeper集群启动时和ZooKeper集群
运行期间触发选举机制选举Leader的过程。

1.ZooKeepr集群启动时
假设某个Zoo(e) Keper集群由5台服务器组成,这5台服务器的myid按照1~5编号,从服
务器1开始,依此启动每台服务器的ZooKeper服务,从而启动ZooKeper集群,此时,选举
Leader的过程如下。

(1)服务器1启动ZooKeper服务,当ZooKeper服务启动后,先投票给自己,并将投票
信息发送给其他服务器启动的ZooKeper服务,投票信息中包含自身的myid和zxid,不过此
时服务器1只有1票,不符合得票数大于服务器总数一半的规则,所以ZooKeper集群还没有
选举出Leader。
(2)服务器2启动ZooKeper服务,当ZooKeper服务启动后,先投票给自己,然后将投
票信息发送给其他服务器启动的ZooKeper服务,并接收其他服务器发送的投票信息,当服
务器2的ZooKeper服务接收到服务器1的ZooKeper服务发送的投票信息之后,会比较两
者投票信息中的zxid和myid,如果zxid相等,则比较myid。由于启动ZooKeper集群时zxid 
中的值为0,而服务器2中ZooKeper服务的myid大于服务器1中ZooKeper服务的myid, 
所以服务器2中ZooKeper服务的投票不会改变。
(3)服务器1中的ZooKeper服务接收到服务器2中ZooKeper服务的投票信息之后, 
同样会比较两者投票信息中的zxid和myid,由于两者zxid的值都等于0,而服务器2中
ZooKeper服务的myid大于服务器1中ZooKeper服务的myid,所以服务器1中的
ZooKeper服务会将投给自身的票转投给服务器2的ZooKeper服务,不过此时服务器2的
投票数仍然不符合得票数大于服务器总数一半的规则。
(4)服务器3启动ZooKeper服务,当ZooKeper服务启动后,先投票给自己,然后将投
票信息发送给其他服务器启动的ZooKeper服务,并接收其他服务器发送的投票信息,当服
务器3的ZooKeper服务接收到服务器1和服务器2的ZooKeper服务发送的投票信息之
后,会依次比较三者投票信息中的zxid和myid。由于启动ZooKeper集群时zxid中的值为

138 
Hadoop大数据技术原理与应用(第2版) 

0,而服务器3中ZooKeper服务的myid大于服务器1和服务器2中ZooKeper服务的
myid,所以服务器3中ZooKeper服务的投票不会改变。

(5)服务器1和服务器2中的ZooKeper服务接收到服务器3中ZooKeper服务的投票
信息之后,同样会比较两者投票信息中的zxid和myid。由于两者zxid的值都等于0,而服务
器3中ZooKeper服务的myid大于服务器1和服务器2中的ZooKeper服务的myid,所以
服务器1中的ZooKeper服务会将投给服务器2中ZooKeper服务的票转投给服务器3的
ZooKeper服务,并且服务器2的ZooKeper服务会将投给自身的票转投给服务器3的
ZooKeper服务,此时服务器3的ZooKeper服务获得了3张投票,符合得票数大于服务器总
数一半的规则,因此服务器3的ZooKeper服务被选举为Leader,选举结束。
(6)服务器1和服务器2已经启动的ZooKeper服务,以及后续服务器4和服务器5启
动的ZooKeper服务都会成为Folower。
2.ZooKeeper集群运行期间
对于正常运行的ZooKeper集群,一旦Leader角色的ZooKeper服务中途宕机,则需要
从其他角色为Folower的ZooKeper服务中重新选举出一个新的Leader。假设运行的
ZooKeper集群由5台服务器构成,服务器3中ZooKeper服务的角色为Leader,当服务器3 
中的ZooKeper服务宕机时,选举Leader的过程如下。

(1)ZooKeper服务的角色为Folower的服务器1、服务器2、服务器4和服务器5会将
自己的状态变为Looking(竞选状态)。

(2)服务器1、服务器2、服务器4和服务器5的ZooKeper服务会先给自己投票,然后分
别将自身的投票信息发送给其他服务器的ZooKeper服务,由于ZooKeper集群在运行过程
中,每个ZooKeper服务的zxid都可能不同,因此假定服务器1、服务器2、服务器4和服务器
5的ZooKeper服务中的zxid分别为99 、101 、100和101 。
(3)服务器1、服务器2、服务器4和服务器5的ZooKeper服务接收来自各个服务器的
投票信息,并且将自身的投票信息与其他服务器中ZooKeper服务发送的投票信息进行
比较。
(4)由于服务器2和服务器5中ZooKeper服务的zxid大于服务器1和服务器4中
ZooKeper服务的zxid,所以服务器1和服务器4的ZoKeper服务会退出竞选,将角色变更为
Folower。
(5)当服务器1和服务器4的ZooKeper服务接收到服务器2和服务器5的ZooKeper 
服务发送的投票信息后,最终会投票给服务器5的ZooKeper服务,这是因为服务器5中
ZooKeper服务的myid大于服务器2中ZooKeper服务的myid,并且服务器2的ZooKeper 
服务也会将投给自身的票转投给服务器5的ZooKeper服务,此时服务器5的ZooKeper服
务获得了3张投票,符合得票数大于服务器总数一半的规则,因此服务器5的ZooKeper服务
被选举为新的Leader,选举结束。
(6)服务器2的ZooKeper服务退出竞选,将角色变更为Folower。
5.部署ZoKer集群
6 
oep

ZooKeper集群的部署模式分为伪分布式模式和完全分布式模式,其中,伪分布式模式是
指在单台服务器中部署ZooKeper集群,ZooKeper集群中的多个ZooKeper服务运行在单


第5章 ZooKeeper分布式协调服务1 39 
台服务器的不同进程中;完全分布式模式是指在多台服务器中部署ZooKeeper集群, 
ZooKeeper集群中的每个ZooKeeper服务都运行在单独的服务器中。本节将分别演示如何在
伪分布式模式和完全分布式模式下部署ZooKeeper集群。
5.6.1 基于伪分布式模式部署ZooKeeper集群
这里以虚拟机Hadoop3为例,演示如何基于伪分布式模式部署ZooKeeper集群,该集群由3 
个ZooKeeper服务组成,这3个ZooKeeper服务的角色分别是Leader、Follower和Observer。
1.下载ZooKeeper安装包
本书使用的ZooKeeper版本为3.7.0,读者可自行到ZooKeeper官网下载ZooKeeper的安
装包apache-zookeeper-3.7.0-bin.tar.gz。
2.创建目录
由于后续还会使用虚拟机Hadoop3部署完全分布式模式的ZooKeeper集群,所以为了避
免安装目录产生冲突,这里在虚拟机Hadoop3的/export/servers目录执行“mkdirzookeeper” 
命令,创建zookeeper目录,在该目录中存放基于伪分布式模式部署的ZooKeeper集群的安装
目录。
3.安装ZooKeeper 
将下载的ZooKeeper安装包apache-zookeeper-3.7.0-bin.tar.gz上传至虚拟机Hadoop3 
的/export/software/zookeeper目录。上传完成后,将ZooKeeper安装包以解压缩的方式安装
至/export/servers/zookeeper目录,在/export/software目录执行如下命令。 
$ tar -zxvf apache-zookeeper-3.7.0-bin.tar.gz -C /export/servers/zookeeper 
上述命令执行完成后,会在/export/servers/zookeeper目录中生成apache-zookeeper- 
3.7.0-bin目录,该目录为ZooKeeper的安装目录,不过此时ZooKeeper集群还无法使用,还需
要对其进行配置。
4.复制ZooKeeper安装目录
为了在单台虚拟机中启动3 个ZooKeeper 服务,这里需要在虚拟机中安装3 个
ZooKeeper,安装的每个ZooKeeper都会启动独立的ZooKeeper服务。出于便捷性的考虑,这
里通过复制ZooKeeper安装目录的方式继续安装另外两个ZooKeeper。另外,为了便于区分, 
这里分别将3个ZooKeeper的安装目录重命名为zookeeper-3.7.0-001、zookeeper-3.7.0-002和
zookeeper-3.7.0-003。在/export/servers/zookeeper目录执行下列命令,复制ZooKeeper安装
目录并重命名。 
$ mv apache-zookeeper-3.7.0-bin zookeeper-3.7.0-001 
$ cp -r zookeeper-3.7.0-001 zookeeper-3.7.0-002 
$ cp -r zookeeper-3.7.0-001 zookeeper-3.7.0-003 
5.创建ZooKeeper配置文件
ZooKeeper安装目录的conf目录下存放了ZooKeeper配置文件的模板文件zoo_sample. 
cfg,该文件包含ZooKeeper的默认配置信息,如果需要修改ZooKeeper的默认配置,则需要将
模板文件zoo_sample.cfg重命名为zoo.cfg,并对zoo.cfg文件的内容进行修改。在3 个
ZooKeeper安装目录的conf目录下,依次执行如下命令,将模板文件zoo_sample.cfg重命名
为zoo.cfg。

Hadoop大数据技术原理与应用(第1 40 2版) 
$ cp zoo_sample.cfg zoo.cfg 
6.修改ZooKeeper配置文件
由于3个ZooKeeper服务运行在同一台虚拟机中,因此为了避免不同ZooKeeper服务使
用的数据持久化目录和端口号产生冲突,这里分别修改3个ZooKeeper安装目录的配置文件。
首先,在/export/servers/zookeeper/zookeeper-3.7.0-001/conf目录下执行“vizoo.cfg”命
令,编辑文件zoo.cfg修改其内容,文件zoo.cfg修改完成的效果如文件5-1所示。
文件5-1 zoo.cfg 
1 #The number of milliseconds of each tick 
2 tickTime=2000 
3 #The number of ticks that the initial 
4 #synchronization phase can take 
5 initLimit=10 
6 #The number of ticks that can pass between 
7 #sending a request and getting an acknowledgement 
8 syncLimit=5 
9 #the directory where the snapshot is stored. 
10 #do not use /tmp for storage, /tmp here is just 
11 #example sakes. 
12 #设置数据持久化目录
13 dataDir=/export/data/zookeeper/zkdata001 
14 #the port at which the clients will connect 
15 #设置客户端连接当前ZooKeeper 服务使用的端口号
16 clientPort=2181 
17 #the maximum number of client connections. 
18 #increase this if you need to handle more clients 
19 #maxClientCnxns=60 
20 #Be sure to read the maintenance section of the 
21 #administrator guide before turning on autopurge. 
22 #http://ZooKeeper.apache.org/doc/current/ZooKeeperAdmin.html# 
23 #sc_maintenance 
24 #The number of snapshots to retain in dataDir 
25 #autopurge.snapRetainCount=3 
26 #Purge task interval in hours 
27 #Set to "0" to disable auto purge feature 
28 #autopurge.purgeInterval=1 
29 #设置ZooKeeper 集群中每个ZooKeeper 服务的地址及端口号
30 server.1=hadoop3:2888:3888 
31 server.2=hadoop3:2889:3889 
32 server.3=hadoop3:2890:3890:observer 
文件5-1中,第13行代码指定ZooKeeper的数据持久化目录为/export/data/zookeeper/ 
zkdata001。
第16行代码指定ZooKeeper服务使用的端口号为2181。
第30 行代码指定编号为1 的ZooKeeper服务的地址为hadoop3:2888:3888,其中, 
hadoop3表示ZooKeeper服务所在的服务器主机名;2888表示当前ZooKeeper服务与Leader 
进行通信的端口;3888表示当前ZooKeeper选举Leader时使用的端口。
第31行代码指定编号为2的ZooKeeper服务的地址为hadoop3:2889:3889。
第32行代码指定编号为3的ZooKeeper服务的地址为hadoop3:2890:3890:observer,其
中,添加的“:observer”用于指定当前ZooKeeper服务的角色为Observer。