第一章 ZooKeeper是什么
一 简介
Zookeeper(ZK): 是一个分布式的、开源的程序协调服务,是 hadoop 项目下的一个子项目。他提供的主要功能包括:配置管理、名字服务、分布式锁、集群管理。
- zookeeper 英译为动物园管理员,他是用来管 hadoop(大象)、Hive(蜜蜂)、pig(小 猪)的管理员, Apache Hbase 和 Apache Solr 的分布式集群都用到了 zookeeper
- 关于ZK的核心思想 ,可以查看豆瓣上的这篇文章 Zookeeper全解析——Paxos(怕馊死)小岛选举思想
二 架构图

ZooKeeper:提供通用的分布式锁服务,用以协调分布式应用
三 作用
- 配置管理
在我们的应用中除了代码外,还有一些就是各种配置。比如数据库连接等。一般我们都 是使用配置文件的方式,在代码中引入这些配置文件。当我们只有一种配置,只有一台服务器,并且不经常修改的时候,使用配置文件是一个很好的做法,但是如果我们配置非常多, 有很多服务器都需要这个配置,这时使用配置文件就不是个好主意了。这个时候往往需要寻找一种集中管理配置的方法,我们在这个集中的地方修改了配置,所有对这个配置感兴趣的 都可以获得变更。Zookeeper 就是这种服务,它使用 Zab 这种一致性协议来提供一致性。现 在有很多开源项目使用 Zookeeper 来维护配置,比如在 HBase 中,客户端就是连接一个 Zookeeper,获得必要的 HBase 集群的配置信息,然后才可以进一步操作。还有在开源的消息队列 Kafka 中,也使用 Zookeeper来维护broker的信息。在 Alibaba开源的 SOA 框架Dubbo 中也广泛的使用 Zookeeper 管理一些配置来实现服务治理
- 名字服务
我们在应用中会存在很多这类问题,特别是在我们的服务特别多的时候, 如果我们在本地保存服务的地址的时候将非常不方便,但是如果我们只需要访问一个大家都 熟知的访问点,这里提供统一的入口,那么维护起来将方便得多了。
分布式锁
Zookeeper 是一个分布式协调服务。这样我们就可以利 用 Zookeeper 来协调多个分布式进程之间的活动。比如在一个分布式环境中,为了提高可靠性,我们的集群的每台服务器上都部署着同样的服务。但是,一件事情如果集群中的每个服务器都进行的话,那相互之间就要协调,编程起来将非常复杂。而如果我们只让一个服务进 行操作,那又存在单点。通常还有一种做法就是使用分布式锁,在某个时刻只让一个服务去干活,当这台服务出问题的时候锁释放,立即 fail over 到另外的服务。这在很多分布式系统 中都是这么做,这种设计有一个更好听的名字LeaderElection(leader 选举)。
- 集群管理
在分布式的集群中,经常会由于各种原因,比如硬件故障,软件故障,网络问题,有些 节点会进进出出。有新的节点加入进来,也有老的节点退出集群。这个时候,集群中其他机 器需要感知到这种变化,然后根据这种变化做出对应的决策。比如我们是一个分布式存储系 统,有一个中央控制节点负责存储的分配,当有新的存储进来的时候我们要根据现在集群目 前的状态来分配存储节点。这个时候我们就需要动态感知到集群目前的状态。
再比如一 个分布式的 SOA 架构中,服务是一个集群提供的,当消费者访问某个服务时,就需要采用 某种机制发现现在有哪些节点可以提供该服务(这也称之为服务发现,比如 Alibaba 开源的 SOA 框架 Dubbo 就采用了 Zookeeper 作为服务发现的底层机制)。还有开源的 Kafka 队列就 采用了 Zookeeper 作为 Cosnumer 的上下线管理。
在大数据中的应用
- Hadoop,使用Zookeeper的事件处理确保整个集群只有一个NameNode,存储配置信息等.
- HBase,使用Zookeeper的事件处理确保整个集群只有一个HMaster,察觉HRegionServer联机和宕机,存储访问控制列表等.
四 ZK集群特点


集群状态
Zookeeper的核心是原子广播,这个机制保证了各个server之间的同步。实现这个机制的协议叫做Zab协议。恢复模式
当服务启动或者在领导者崩溃后,Zab就进入了恢复模式。
当领导者被选举出来,且大多数server的完成了和leader的状态同步以后,恢复模式就结束了。
状态同步保证了leader和server具有相同的系统状态广播模式
需要保证proposal被按顺序处理,因此zk采用了递增的事务id号(zxid)来保证。
所有的提议(proposal)都在被提出的时候加上了zxid。
实现中zxid是一个64为的数字,它高32位是epoch(epoch也称为纪元数字)用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch,低32位是个递增计数。
总结
- 恢复模式 安其内
无主,无服务
选举leader
- 广播模式 壤其外
主从模式
leader维护事务的唯一和有序性
队列机制
Server状态
LOOKING:当前Server不知道leader是谁,正在搜寻
LEADING:当前Server即为选举出来的leader
FOLLOWING:leader已经选举出来,当前Server与之同步
主从分工
- 领导者(leader)
负责进行投票的发起和决议,更新系统状态,(增删改) - 学习者(learner)
包括跟随者(follower)和观察者(observer),follower用于接受客户端请求并向客户端返回结果,在操作过程中参与投票; Observer可以接受客户端连接,将写请求转发给leader,但observer不参加投票过程,只同步leader的状态,observer的目的是为了扩展系统,提高读取速度
- 客户端(client)
请求发起方
五 Leader的选举过程
- 1.判定(zxid,myid);2.投票传递
zxid <从paxos 到 zookeeper>
myid
- 首先选举zxid最大的
如果zxid相同,则选举myid最大的
- Leader选举
选举过程耗时在200ms之内,一般情况下zookeeper恢复服务时间间隔不超过200ms

五 Zookeeper存储结构—Znode
Zookeeper 底层是一套数据结构。这个存储结构是一个树形结构,其上的每一个节点, 我们称之为“znode”

特点
- 层次的,目录型结构,便于管理逻辑关系
- 节点znode而非文件file
- znode信息
包含最大1MB的数据信息
记录了zxid等元数据信息
节点类型
znode有两种类型,临时的(ephemeral)和持久的(persistent)
znode支持序列SEQUENTIAL
- (1)PERSISTENT 持久化节点:
所谓持久节点,是指在节点创建后,就一直存在,直到有删除操作来主动清除这个节点。否则不会因为创建该节点的客户端会话失效而消失。
- (2)PERSISTENT_SEQUENTIAL 持久顺序节点
这类节点的基本特性和上面的节点类 型是一致的。额外的特性是,在 ZK 中,每个父节点会为他的第一级子节点维护一份时序, 会记录每个子节点创建的先后顺序。基于这个特性,在创建子节点的时候,可以设置这个属性,那么在创建节点过程中,ZK 会自动为给定节点名加上一个数字后缀,作为新的节点名。 这个数字后缀的范围是整型的最大值。 在创建节点的时候只需要传入节点 “/test_”,这样 之后,zookeeper 自动会给”test_”后面补充数字。
- (3)EPHEMERAL 临时节点:
和持久节点不同的是,临时节点的生命周期和客户端会话绑定。也就是说,如果客户端会话失效,那么这个节点就会自动被清除掉。注意,这里提到的是会话失效,而非连接断开。另外,在临时节点下面不能创建子节点。 这里还要注意一件事,就是当你客户端会话失效后,所产生的节点也不是一下子就消失 了,也要过一段时间,大概是 10 秒以内,可以试一下,本机操作生成节点,在服务器端用 命令来查看当前的节点数目,你会发现客户端已经 stop,但是产生的节点还在。
- (4) EPHEMERAL_SEQUENTIAL 临时自动编号节点:
此节点是属于临时节点,不过带 有顺序,客户端会话结束节点就消失。
六 事件监听机制
未使用ZK之前
- 客户端轮询指定节点下的数据
- 通过网络轮询,代价很大

使用ZK后——基于通知(notification)的机制
- 客户端向ZooKeeper注册需要接收znode通知
- 通过对znode设置监视点(watch)来接收通知。监视点是一个单次触发的操作,意即监视点会触发一个通知。
- 为了接收多个通知,客户端必须在每次通知后设置一个新的监视点。

事件监听Watcher
Watcher 在 ZooKeeper 是一个核心功能,Watcher 可以监控目录节点的数据变化以及子目录的变化, 一旦这些状态发生变化,服务器就会通知所有设置在这个目录节点上的Watcher,从而每个客户端都很快知道它所关注的目录节点的状态发生变化,而做出相应的反应
- 可以设置观察点的操作:exists,getChildren,getData
- 可以触发观察的操作:create,delete,setData
第二章 ZooKeeper的安装
安装单机版1
1、安装Linux和JDK,并配置环境变量,jdk资源见上篇博文,并且需要将资源解压到/usr/local目录下
export JAVA_HOME=/usr/local/jdk export (jdk名称)
CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$JAVA_HOME/bin:$PATH
2、上传Zookeeper到Linux并解压到/usr/local目录下
常用的命令
解压命令# tar -zxf zookeeper-3.4.6.tar.gz
复制文件夹命令# cp zookeeper-3.4.6 /usr/local/zookeeper -r
3、目录结构
1. bin:放置运行脚本和工具脚本,如果是 Linux 环境还会有有 zookeeper 的运 行日志 zookeeper.out
2. conf:zookeeper 默认读取配置的目录,里面会有默认的配置文件
3. contrib:zookeeper 的拓展功能
4. dist-maven:zookeeper的 maven 打包目录
5. docs:zookeeper 相关的文档
6. lib:zookeeper 核心的 jar
7. recipes:zookeeper 分布式相关的 jar 包
8. src:zookeeper 源码
4、配置Zookeeper
Zookeeper 在启动时默认的去 conf 目录下查找一个名称为 zoo.cfg 的配置文件。 在 zookeeper 应用目录中有子目录 conf。其中有配置文件模板:zoo_sample.cfg, 执行cp zoo_sample.cfg zoo.cfg。将zookeeper 应用中默认的配置文件复制为 conf/zoo.cfg。 修改配置文件vim zoo.cfg- 设置数据缓存路径 , 如果没有data目录需要手动创建
5、启动Zookeeper
默认加载配置文件:./zkServer.sh start:默认的会去 conf 目录下加载 zoo.cfg 配置文件。
指定加载配置文件:./zkServer.sh start 配置文件的路径。
安装集群版
Zookeeper集群中的角色

基于Zookeeper实现 RPC_RMI部署集群服务_消费_服务发现_服务的原理

过程分析
(0)服务容器负责启动,加载,运行服务提供者。
(1)服务提供者在启动时,向注册中心注册自己提供的服务 URL。
(2)服务消费者在启动时,向注册中心订阅自己所需的服务。
(3)注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接通知变更数据给消费者。
(4)服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如 果调用失败,再选另一台调用。 让消费能够感知到服务提供者的状态发生了变化(宕机,重启)
集群安装
1、提供数据缓存服务
在 zookeeper01 应用目录中,创建 data 目录,用于缓存应用运行数据
cd zookeeper01
mkdir data
2、复制应用
复制两份Zookeeper 应用。用于模拟集群中的 3 个节点。
复制文件夹# cp -r zookeeper01 zookeeper02
cp -r zookeeper01 zookeeper03
3、提供配置文件
将conf目录下的配置文件模板:zoo_sample.cfg改为zookeeper 应用中的配置文件 zoo.cfg。
复制文件并修改名称# `cp zoo_sample.cfg zoo.cfg`
4、修改配置文件zoo.cfg
查看文件所在路径命令 # pwd /data , 然后在第6步配置dataDir中使用
5、提供唯一标识
在每个Zookeeper的data目录下使用
创建myid文件并写入唯一标识# `echo [唯一标识] >> myid`
6、修改配置文件 zoo.cfg - 设置服务、投票、选举端口
注:server.[唯一标识] (中间是点号)
vi zoo.cfg
clientPort=2181 #服务端口根据应用做对应修改,zk01-2181,zk02-2182,zk03-2183
server.1=192.168.179.131:2881:3881
server.2=192.168.179.131:2882:3882
server.3=192.168.179.131:2883:3883

7、启动应用
在bin目录下
- 每个Zookeeper目录下启动
./zkServer.sh start - 每个Zookeeper目录下状态
./zkServer.sh status - 每个Zookeeper目录下关闭
./zkServer.sh stop
8、创建集群启动脚本
注意:
- 如果服务器的安全性比较高, 建议在第6步时直接将服务器的ip改为本机ip
127.0.0.1:2181:3881这样可以避免防火墙或者是其他情况导致的问题 - 如果设置了安全组或者防火墙, 需要将zk通信所用的端口全部放开!!!
创建一个脚本文件并编写内容
vim startall.sh
文本内容
./zookeeper01/bin/zkServer.sh start
./zookeeper02/bin/zkServer.sh start
./zookeeper03/bin/zkServer.sh start
赋予该文件运行的权限
chmod +x startall.sh /sudo chmod 777 startall.sh
运行该脚本(其他脚本制作同上)
./startall.sh
9、控制台访问 ZooKeeper 应用
命令格式为:
zkCli.sh -server host:port #默认连接 localhost:2181
第三章 zookeeper操作
随便输入一串字符, ZK命令行即可提示我们相关命令
创建查询与删除

# 相关参数介绍
cZxid:节点创建时的zxid
ctime:节点创建时间
mZxid:节点最近一次更新时的zxid
mtime:节点最近一次更新的时间
cversion:子节点数据更新次数
dataVersion:本节点数据更新次数
aclVersion:节点ACL(授权信息)的更新次数
ephemeralOwner:如果该节点为临时节点, ephemeralOwner值表示与该节点绑定的session id. 如果该节点不是临时节点,ephemeralOwner值为0

其他操作
connect host:port - 在集群中连接其他的 ZooKeeper 应用。
ls path - 列表路径下的资源。在 ZooKeeper 控制台客户端中,没有默认列表功能,必须 指定要列表资源的位置。
如: ls / ; ls /path 等。
create [-e] [-s] path data - 创建节点
如: create /test 123 创建一个/test 节点,节点携 带数据信息 123。
create -e /test 123 创建一个临时节点/test,携带数据为 123,临时节点只 在当前会话生命周期中有效,会话结束节点自动删除。
create -s /test 123 创建一个顺序节点 /test,携带数据123,创建的顺序节点由ZooKeeper自动为节点增加后缀信息,如-/test00000001 等。-e 和-s 参数可以联合使用。
get path - 查看指定节点的数据。
set path data [version] - 设置对应位置节点的数据。
如: set /test 'test data'。 如果要设 置的数据中有空格,则使用单引号界定数据的范围。每次修改数据后,
dataVersion 属性自增。 那么在 set 命令中可以指定 version,version 数据必须与上次查询的值一致,用于保证本次修改命令执行时,没有其他会话修改此数据。
delete path [version] - 删除指定节点,此命令不能删除有子节点的节点。
如:delete /test。 其中 version 参数和 set 命令的 version 含义一致
rmr path - 删除指定结点,包括子节点。
quit - 退出控制台
链接:https://pan.baidu.com/s/1Z8lycx4L8qhP_ZF42TypaA
提取码:epll
复制这段内容后打开百度网盘手机App,操作更方便哦
- zookeeper下载 ↩

