Zookeeper 是 Hadoop 中非常重要的组件,它的主要功能是为分布式系统提供一致性协调服务,提供的功能包括配置维护、域名服务、分布式同步和组服务等。Google 中类似服务叫作 Chubby。
Zookeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是 Google 的 Chubby 的开源实现,是 Hadoop 和 HBase 的重要组件。主要用来解决分布式集群中应用系统的一致性问题。ZooKeeper 本质上是一个分布式的小文件存储系统。提供基于类似于文件系统的目录树方式的数据存储,并且可以对树中的节点进行有效管理。从而用来维护和监控你存储的数据的状态变化。通过监控这些数据状态的变化,从而可以达到基于数据的集群管理。ZooKeeper 的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。
ZooKeeper 包含一个简单的原语集,提供 Java 和 C 的接口。
ZooKeeper 代码版本中,提供了分布式独享锁、选举、队列的接口。其中分布锁和队列有 Java 和 C 两个版本,选举只有 Java 版本。
那么 Zookeeper 能做什么事情呢,简单的例子:使用 Zookeeper 可以保证总服务器自动感知有多少提供搜索引擎的服务器并向这些服务器发出搜索请求,当总服务器宕机时自动启用备用的总服务器。应用场景:
注意:ZK 主要是用来管理其他框架的,单独使用没有任何意义。类似于动物园中的管理员:
Zookeeper 特性:
Zookeeper 集群搭建指的是 ZooKeeper 分布式模式安装。通常由 2n+1(奇数)
台 Server 组成。这是因为为了保证 Leader 选举(基于 Paxos 算法的实现)能过得到多数的支持,所以 ZooKeeper 集群的数量一般为奇数。Zookeeper 运行需要 java 环境,所以需要提前安装 jdk,关于 jdk 的安装笔者这里不再赘述。对于安装 Leader+Follower 模式的集群,大致过程如下:
说明:如果要想使用 Observer 模式,可在对应节点的配置文件添加如下配置:
peerType=observer
其次,必须在配置文件指定哪些节点被指定为 Observer,如:
server.1:bigdata01:2181:3181:observer
server.1:192.168.61.100:2181:3181:observer
这里,我们安装的是 Leader + Follower 模式:
服务器IP | 主机名 | myid的值 |
---|---|---|
192.168.61.100 | bigdata01 | 1 |
192.168.61.101 | bigdata02 | 2 |
192.168.61.102 | bigdata03 | 3 |
下面进行具体的步骤演示:
(1) 将本地的 bigdata01、bigdata02、bigdata03 启动,并且使用 SecureCRT 进行连接。
(2) 使用 SecureCRT 把 apache-zookeeper-3.5.8-bin.tar.gz
的安装包上传到 /data/soft/
目录下。笔者可以通过 http://archive.apache.org/dist/zookeeper/ 进行 zookeeper 安装包的下载。
(3) 在 bigdata01 节点上,进入到 /data/soft
目录,解压 zookeeper 的压缩包进行安装。命令:cd /data/soft/、tar -zxvf apache-zookeeper-3.5.8-bin.tar.gz。
bin 目录:Zookeeper 的可执行脚本目录,包括 Zookeeper 服务进程、Zookeeper 客户端等脚本。其中,.sh
是 Linux 环境下的脚本,.cmd
是 Windows 环境下的脚本。conf 目录:配置文件目录。其中 zoo_sample.cfg
为样例配置文件,需要修改为自己的名称,一般为 zoo.cfg
。log4j.properties
为日志配置文件。lib:Zookeeper 依赖的包。
(4) 在 bigdata01 节点上,修改配置文件。命令如下:
mv apache-zookeeper-3.5.8-bin zookeeper-3.5.8
cd zookeeper-3.5.8/conf/
cp zoo_sample.cfg zoo.cfg
mkdir -p /data/soft/zookeeper-3.5.8/zkdatas/
vi zoo.cfg 修改如下:
dataDir=/data/soft/zookeeper-3.5.8/zkdatas -- zookeeper的数据存放目录
autopurge.snapRetainCount=3 --保留多少个快照
autopurge.purgeInterval=1 --日志多少小时清理一次
-- 集群中服务器地址
server.1=bigdata01:2888:3888
server.2=bigdata02:2888:3888
server.3=bigdata03:2888:3888
(5) 添加 myid 配置。命令:echo 1 > /data/soft/zookeeper-3.5.8/zkdatas/myid
(6) 把配置好的 zookeeper 拷贝到其他两个节点。命令:
scp -rq /data/soft/zookeeper-3.5.8/ bigdata02:/data/soft/
scp -rq /data/soft/zookeeper-3.5.8/ bigdata03:/data/soft/
(7) 修改 bigdata02、bigdata03 节点上的 myid 文件。命令:
echo 2 > /data/soft/zookeeper-3.5.8/zkdatas/myid
echo 3 > /data/soft/zookeeper-3.5.8/zkdatas/myid
(8) 三个节点启动 zookeeper 服务。命令:
bigdata01 节点:
[root@bigdata01 ~]# cd /data/soft/zookeeper-3.5.8/bin/
[root@bigdata01 bin]# zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /data/soft/zookeeper-3.5.8/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
bigdata02 节点:
[root@bigdata02 ~]# cd /data/soft/zookeeper-3.5.8/bin/
[root@bigdata02 bin]# zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /data/soft/zookeeper-3.5.8/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
bigdata03 节点:
[root@bigdata03 ~]# cd /data/soft/zookeeper-3.5.8/bin/
[root@bigdata03 bin]# zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /data/soft/zookeeper-3.5.8/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
(9) 三个节点分别查看启动状态。命令:
[root@bigdata01 bin]# zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /data/soft/zookeeper-3.5.8/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: follower
[root@bigdata02 bin]# zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /data/soft/zookeeper-3.5.8/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: leader
[root@bigdata03 bin]# zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /data/soft/zookeeper-3.5.8/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: follower
分别在 bigdata01、bigdata02、bigdata03 上执行 jps 命令验证是否有 QuorumPeerMain 进程如果都有就说明 zookeeper 集群启动正常了。例如:
如果没有就到对应的节点的 logs 目录下查看 zookeeper*-*.out
日志文件。
Zookeeper 节点类型。Znode 有两种,分别为 临时节点
和 永久节点
。节点的类型在创建时即被确定,并且不能改变。临时节点:该节点的生命周期依赖于创建它们的会话。一旦会话结束,临时节点将被自动删除,当然可以也可以手动删除。临时节点不允许拥有子节点。永久节点:该节点的生命周期不依赖于会话,并且只有在客户端显示执行删除操作的时候,他们才能被删除。
Znode 还有一个序列化的特性,如果创建的时候指定的话,该 Znode 的名字后面会自动追加一个不断增加的序列号。序列号对于此节点的父节点来说是唯一的,这样便会记录每个子节点创建的先后顺序。它的格式为 %10d
(10位数字,没有数值的数位用 0 补充,例如 0000000001
)。这样便会存在四种类型的 Znode 节点,分别对应:
首先运行 zkCli.sh –server ip 进入命令行工具,quit 命令退出会话窗口,如下:
zkCli.sh -- 默认进入当前主机(节点)命令行工具
zkCli.sh -server bigdata01:2181 -- 进入指定主机(节点)命令行工具
quit 退出
ctrl + l 清屏
命令 | 说明 | 参数 |
---|---|---|
create [-s] [-e] path data acl | 创建Znode | -s 指定是顺序节点 -e 指定是临时节点 |
ls path [watch] | 列出Path下所有子Znode | |
get path [watch] | 获取Path对应的Znode的数据和属性 | |
ls2 path [watch] | 查看Path下所有子Znode以及子Znode的属性 | |
set path data [version] | 更新节点 | version 数据版本 |
delete path [version] | 删除节点, 如果要删除的节点有子Znode,则无法删除 | version 数据版本 |
rmr path | 删除节点, 如果有子Znode则递归删除 | |
setquota -n|-b val path | 修改Znode配额 | -n 设置子节点最大个数 -b 设置节点数据最大长度 |
history | 列出历史记录 |
【示例1】创建普通永久节点。命令:create /app1 hello
【示例2】创建顺序(序列化)节点。命令:create -s /app2 world
【示例3】创建临时节点。命令:create -e /tempnode world
【示例4】创建顺序的临时节点。命令:create -s -e /tempnode2 aaa
【示例5】获取节点数据。命令:get /app1
【示例6】修改节点数据。命令:set /app1 hadoop。
【示例7】删除节点(删除的节点不能有子节点)。命令:delete /tempnode20000000004
【示例8】 递归删除。命令:rmr /app1。
节点属性:
节点属性说明如下:
0x0
。在 client 和 server 通信之前,首先需要建立连接,该连接称为 session。连接建立后,如果发生连接超时、授权失败,或者显式关闭连接,连接便处于 CLOSED 状态,此时 session 结束。ZooKeeper 提供了分布式数据发布/订阅功能,一个典型的发布/订阅模型系统定义了一种一对多的订阅关系,能让多个订阅者同时监听某一个主题对象,当这个主题对象自身状态变化时,会通知所有订阅者,使他们能够做出相应的处理。
ZooKeeper 中,引入了 Watcher 机制来实现这种分布式的通知功能。ZooKeeper 允许客户端向服务端注册一个 Watcher 监听,当服务端的一些事件触发了这个 Watcher,那么就会向指定客户端发送一个事件通知来实现分布式的通知功能。触发事件种类很多,如:节点创建,节点删除,节点改变,子节点改变等。总的来说可以概括 Watcher 为以下三个过程:客户端向服务端注册 Watcher、服务端事件发生触发 Watcher、客户端回调 Watcher 得到触发事件情况。
一次性触发:事件发生触发监听,一个 WatcherEvent 就会被发送到设置监听的客户端,这种效果是一次性的,后续再次发生同样的事件,不会再次触发。同一个事件类型在不同的通知状态中代表的含义有所不同,下表列举了常见的通知状态和事件类型。
KeeperState | EventType | 触发条件 | 说明 |
---|---|---|---|
None | 连接成功 | ||
SyncConnected | NodeCreated | Znode被创建 | 此时处于连接状态 |
SyncConnected | NodeDeleted | Znode被删除 | 此时处于连接状态 |
SyncConnected | NodeDataChanged | Znode数据被改变 | 此时处于连接状态 |
SyncConnected | NodeChildChanged | Znode的子Znode数据被改变 | 此时处于连接状态 |
Disconnected | None | 客户端和服务端断开连接 | 此时客户端和服务器处于断开连接状态 |
Expired | None | 会话超时 | 会收到一个SessionExpiredExceptio |
AuthFailed | None | 权限验证失败 | 会收到一个AuthFailedException |
其中连接状态事件(type=None, path=null)不需要客户端注册,客户端只要有需要直接处理就行了。
事件封装:ZooKeeper 使用 WatchedEvent 对象来封装服务端事件并传递。WatchedEvent 包含了每一个事件的三个基本属性:通知状态(keeperState),事件类型(EventType)和节点路径(path)
event 异步发送:Watcher 的通知事件从服务端发送到客户端是异步的。
先注册再触发:Zookeeper 中的 Watch 机制,必须客户端先去服务端注册监听,这样事件发送才会触发监听,通知给客户端。
--1.设置节点数据变动监听:
get /app20000000002 watch
'get path [watch]' has been deprecated. Please use 'get [-s] [-w] path' instead.
--2.通过另一个客户端更改节点数据:
set /app20000000002 world
Zookeeper 默认的算法是 FastLeaderElection,采用投票数大于半数则胜出的逻辑。
假设目前有 5 台服务器,每台服务器均没有数据,它们的编号分别是 1、2、3、4、5,按编号依次启动,它们的选举过程如下:
对于运行正常的 Zookeeper 集群,中途有机器宕掉,需要重新选举时,选举过程就需要加入数据 ID、服务器 ID 和逻辑时钟。
根据这个规则选出 Leader。
在分布式场景下,ZooKeeper 是如何实现数据一致性的呢?Zab 一致性协议。ZooKeeper 是通过 Zab 协议来保证分布式事务的最终一致性。Zab(ZooKeeper Atomic Broadcast,ZooKeeper 原子广播协议)支持崩溃恢复,基于该协议,ZooKeeper 实现了一种主备模式的系统架构来保持集群中各个副本之间数据一致性。系统架构可以参考下面这张图:
在 ZooKeeper 集群中,所有客户端的请求都是写入到 Leader 进程中的,然后,由 Leader 同步到其他节点,称为 Follower。在集群数据同步的过程中,如果出现 Follower 节点崩溃或者 Leader 进程崩溃时,都会通过 Zab 协议来保证数据一致性。Zab 协议的具体实现可以分为以下两部分:
1、消息广播阶段。 Leader 节点接受事务提交,并且将新的 Proposal 请求广播给 Follower 节点,收集各个节点的反馈,决定是否进行 Commit,在这个过程中,也会使用 Quorum 选举机制。
2、崩溃恢复阶段。 如果在同步过程中出现 Leader 节点宕机,会进入崩溃恢复阶段,重新进行 Leader 选举,崩溃恢复阶段还包含数据同步操作,同步集群中最新的数据,保持集群的数据一致性。
整个 ZooKeeper 集群的一致性保证就是在上面两个状态之前切换,当 Leader 服务正常时,就是正常的消息广播模式;当 Leader 不可用时,则进入崩溃恢复模式,崩溃恢复阶段会进行数据同步,完成以后,重新进入消息广播阶段。
Zab 流程分析。 Zab 的具体流程可以拆分为消息广播、崩溃恢复和数据同步三个过程,下面我们分别进行分析。
1、消息广播。 在 ZooKeeper 中所有的事务请求都由 Leader 节点来处理,其他服务器为 Follower,Leader 将客户端的事务请求转换为事务 Proposal,并且将 Proposal 分发给集群中其他所有的 Follower。完成广播之后,Leader 等待 Follwer 反馈,当有过半数的 Follower 反馈信息后,Leader 将再次向集群内 Follower 广播 Commit 信息,Commit 信息就是确认将之前的 Proposal 提交。Leader 节点的写入也是一个两步操作,第一步是广播事务操作,第二步是广播提交操作,其中 过半数指的是反馈的节点数 >=N/2+1
,N 是全部的 Follower 节点数量。消息广播的过程描述可以参考下图:
2、崩溃恢复。 消息广播通过 Quorum 机制,解决了 Follower 节点宕机的情况,但是如果在广播过程中 Leader 节点崩溃呢?这就需要 Zab 协议支持的崩溃恢复,崩溃恢复可以保证在 Leader 进程崩溃的时候可以重新选出 Leader,并且保证数据的完整性。崩溃恢复和集群启动时的选举过程是一致的,也就是说,下面的几种情况都会进入崩溃恢复阶段:
我们通过一个模拟的例子,来了解崩溃恢复阶段,也就是选举的流程。假设正在运行的集群有五台 Follower 服务器,编号分别是 Server1、Server2、Server3、Server4、Server5,当前 Leader 是 Server2,若某一时刻 Leader 挂了,此时便开始 Leader 选举。
选举过程如下:
3、数据同步。 崩溃恢复完成选举以后,接下来的工作就是数据同步,在选举过程中,通过投票已经确认 Leader 服务器是最大 Zxid 的节点,同步阶段就是利用 Leader 前一阶段获得的最新 Proposal 历史,同步集群中所有的副本。
持续更新。。。。