本文创作的初心是为学习或了解ZooKeeper的童鞋提供帮助,请大家耐心仔细阅读。
目录
一、Zookeeper 是什么 ?
二、Zookeeper 在Hadoop生态中是干什么的?
三、Zookeeper 是怎么实现的?
四、ZooKeeper的基本运转流程
五、Zookeeper 中的事务操作
六、Zookeeper 特点
七、Zookeeper 集群中的三种角色
八、Zookeeper服务器的4种状态
九、选举机制
9.1 被选举成Leader的条件:获得集群中超过一半节点投票的节点才会能被选举成Leader。
9.2 选举流程
十、Zookeeper 的分布式安装(Linux操作系统)
十一、ZooKeeper Java API的使用和动态上下线,Watcher机制
小结
Zookeeper 是起源于雅虎,后来捐献给了Apache,并由Apache开源的一款针对大型分布式系统的可靠协调系统, 是为分布式应用程序提供高性能协调服务。在分布式系统中解决分区容错性和可用性,在一致性方面解决的是保证最终一致性,而不是强一致性,从而满足在一致性、可用性和分区容错性之间的平衡。它包含一个简单的原语集,分布式应用程序可以基于它实现配置维护、命名服务、分布式同步、组服务等。
Zookeeper提供的功能有:集群管理、主从协调、分布式锁、分布式消息队列(发布/订阅)、分布式配置管理、分布式协调/通知、统一命名服务等。还可以用来保证数据在ZK集群之间的数据的事务性一致,其中ZooKeeper提供通用的分布式锁服务,用以协调分布式应用。
Zookeeper作为Hadoop项目中的一个子项目,是 Hadoop集群管理的一个必不可少的模块,它主要用来解决分布式应用中经常遇到的数据管理问题。在Hadoop中,它管理Hadoop集群中的NameNode,用于保证Hadoop集群主节点的高可用;Kafka用Zookeeper来实现消费者的负载均衡和消息状态的管理;还有在Hbase中Master Election、Server 之间状态同状步等。
Zoopkeeper 提供了一套很好的分布式集群管理的机制,就是它这种基于层次型的目录树的数据结构,并对树中的节点进行有效管理,从而可以设计出多种多样的分布式的数据管理模型。
ZooKeeper是以Fast Paxos算法为基础的,Paxos 算法存在活锁的问题,即当有多个proposer交错提交时,有可能互相排斥导致没有一个proposer能提交成功,而Fast Paxos作了一些优化,通过选举产生一个leader (领导者),只有leader才能提交proposer,具体算法可见Fast Paxos。因此,要想弄懂ZooKeeper首先得对Fast Paxos有所了解。这里就不对Fast Paxos做介绍了,感兴趣的同学自行了解一下。
1. 选举Leader。
2. 同步数据。
3. 选举Leader过程中算法有很多,但要达到的选举标准是一致的。
4. Leader要具有最高的执行ID,类似root权限。
5. 集群中大多数的机器得到响应并接受选出的Leader。
在ZooKeeper中,能改变ZooKeeper服务器状态的操作称为事务操作。一般包括数据节点创建与删除、数据内容更新和客户端会话创建与失效等操作。
事务ID:对于每一个事务请求,Zookeeper都会给它分配一个全局唯一的事务ID,用ZXID表示,是一个64位的数字,有Leader统一分配,每次执行完事务操作,ZXID都会递增。每一个ZXID对应一次事务操作,从这些ZXID就可以间接的知道Zookeeper执行这些事务的全局顺序。
1. 最终一致性:在Zookeeper集群中,保证在一段时间内,最终数据能够达到一致(这也是Zookeeper最重要的一个特点)
2. 顺序性:从同一个客户端发起的事务请求,最终会严格按照事务发起的顺序被应用到Zookeeper当中。
3. 可靠性:如果事务操作被到一台ZK服务器接受,那么它将被集群内所有的ZK服务器所接受。
4. 原子性:一次数据更新,要么成功,要么失败,没有中间状态。
5. 单一视图:无论客户端连接到ZK集群当中的哪台服务器,展示给它的都是同一个视图,也就是说集群内每台服务器看到的数据都是一致的。
7.1 Leader(领导者):可以处理事务及非事务请求(读、写 请求)
Leader是整个Zookeeper集群工作的核心,它是由集群中的所有服务器共同选举出来的。
在Zookeeper当中,所有的事务性请求都是由Leader来调度和处理,在处理事务性请求的过程中,Leader要保证从同一个客户端发起的事务请求,最终会严格按照事务发起的顺序被应用到Zookeeper当中。
当然,Leader也可以处理客户端的读请求。
7.2 Follower(跟随者):处理非事务请求(读请求)
Follower会同步Leader的状态,于Leader的状态保持一致,处理客户端发起的非事务性请求(读请求)。
如果客户端向Follower发起一个事务性请求,那Follower会把这个事务性请求转发给Leader,由Leader来处理。
另外,Follower会在选举的时候,参与投票选出Leader。
7.3 Observer(观察者):处理非事务请求并且不参与选举投票(一般情况下,集群没有达到读瓶颈不需要增加Observer节点)
使用observer模式是对读请求进行扩展。通过增加更多的observer,可以接收更多的请求的流量,却不会牺牲写操作的吞吐量。
Observer和Follower比较相似,只有一些小区别:首先observer不参与选举投票也不响应提议;其次是observer不需要将事务持久化到磁盘,一旦observer被重启,需要从leader重新同步整个命名空间。
如果ZooKeeper集群的读取负载很高,或者客户端多到跨机房,可以设置一些observer服务器,来提高读取的吞吐量。
1. LOOKING:此状态为寻找Leader状态,处于该状态需要进入选举流程
2. LEADING:领导者状态,选举完成之后,表明当前服务器角色是Leader
3. FOLLOWING:跟随者状态,选举完成之后,表明当前服务器角色是Follower
4. OBSERVERING:观察者状态,不参加选举,表明当前服务器角色是Observer
为了实现超过一半节点投票,Zookeeper集群一般由奇数台服务器组成。
还有一点需要注意:一个 ZooKeeper 集群如果要对外提供可用的服务,那么集群中必须要有过半的机器正常工作并且彼此之间能够正常通信。基于这个特性,如果想搭建一个能够允许 N 台机器 down 掉的集群,那么就要部署一个由 2*N+1 台服务器构成的 ZooKeeper 集群。
举例说明:
假如说现在有一个3台机器组成的ZK集群,只有超过2个节点同时选某一个节点,那么该节点才能担任Leader。
如果是一个由6台服务器构成的 ZooKeeper 集群,同样只能够挂掉 2 台机器,因为如果挂掉 3 台,剩下的机器就无法实现过半了。(所以ZK集群中服务器个数一般是基数)
9.2.1 全新集群选举
假设我们ZK集群有三台服务器 node01,node02,node03,启动顺序为:node01 --> node02 --> node03
1) 首先我们在搭建zookeeper集群的时候会在每台服务器创建一个myid的配置文件,用来标记此服务器节点的全局唯一,一般是用阿拉伯数字1,2,3...来标记。(后面ZK集群搭建会讲到)
2 )启动ZK服务器的时候首先会检测集群中有没有Leader,由于此节是全新集群启动,着重讲解第一次选举Leader的过程: 启动node01的时候不会出发选举,启动node02的时候触发选举模式 --> 这个时候这两台服务器都处于 LOOKING 状态(寻找Leader状态)
3) 这时候处于LOOKING 状态的机器都会向整个集群中广播一条消息进行投票,消息内容是(myid,ZXID),由于是全新集群搭建使用,所以每台服务器都会投票选择自己,并且事务ID(ZXID)都为0。
node01 --> (1,0);node02 --> (2,0)
4) 然后在投票结束后每台机器开始处理投票
--> ① 先比较ZXID的大小,再比较myid的大小(ZXID相同的时候才会再去比较myid的大小),
② 比较完之后集群会判断是否有半数以上的机器获得投票,如果是,则获得超过半数投票的机器就被选为Leader;否则根据比较结果,选择胜出的节点再次投票,直至有超过集群半数机器获得投票为止。选举出Leader之后,就会更新服务器状态,选举为Leader的服务器的状态从LOOKING更新为LEADING(领导者),其他服务器状态更新为FOLLOWING(跟随者)。
第一次投票:node01 --> (1,0);node02 --> (2,0)
第一次投票结果:没有机器获得超过半数的投票,根据比较结果继续更新投票
第二次投票:node01 --> (2,0);node02 --> (2,0)
第二次投票 结果:node02获得超过集群半数的投票,node02被选为Leader,node02的状态从LOOKING更新为LEADING,node01的状态从LOOKING更新为FOLLOWING。
5) 接下来启动node03,node03启动之后发现已经有Leader了,这个时候node03会进行两步操作:①从Leader服务器(node02)更新数据 ②node03的状态从LOOKING更新为FOLLOWING。
到这里全新集群的选举就结束了,结果是:node02为Leader,node01,node03 为Follower。
9.2.2 运行时选举
在运行过程中,Follower节点或者Observer节点挂掉了,不会影响整个集群的正常工作,但是如果是Leader节点挂掉了,那么整个集群就不能正常工作了,需要选举出新的Leader,才能正常的对外提供服务。选举机制和前边的所介绍的全新集群是相同的。
1) Leader挂掉之后,集群中的其他Follower节点的状态都会从FOLLOWING更新为LOOKING,并且向整个集群中广播一条消息进行投票,消息内容是(myid,ZXID),这里需要说明的是,由于Zookeeper是保证数据的最终一致性,所以在运行期间每台机器的ZXID(事务ID)可能不一样。
2) 然后在投票结束后每台机器开始处理投票 -->① 先比较ZXID的大小,再比较myid的大小(ZXID相同的时候才会再去比较myid的大小),②比较完之后集群会判断是否有半数以上的机器获得投票,如果是,则获得超过半数投票的机器就被选为Leader;否则根据比较结果,选择胜出的节点再次投票,直至有超过集群半数机器获得投票为止。选举出Leader之后,就会更新服务器状态,选举为Leader的服务器的状态从LOOKING更新为LEADING(领导者),其他服务器状态更新为FOLLOWING(跟随者)。
1. 安装包下载 (建议从官网下载合适版本,这里提供的是3.4.10 )
链接:https://pan.baidu.com/s/1WzO1wNyTt40f78V3yi4ilg
提取码:lfsk
2. 上传安装包到/bigdata 目录
cd /bigdata rz
3.解压 zookeeper 安装包
tar –xzvf zookeeper-3.4.10.tar.gz
4.修改解压后的安装包的属主
chown -R root:root zookeeper-3.4.10
5.进入 zookeeper-3.4.10 目录,删除.xml 和.txt 后缀的文件
cd zookeeper-3.4.10
rm –rf *.xml
rm –rf *.txt
6.创建 zookeeper 目录的软链接
ln –s /bigdata/zookeeper-3.4.10 /usr/local/zookeeper
进入到/usr/local 目录下可以看到刚创建的软链接。
7.修改环境变量,在/etc/profile 文件中加入 zookeeper 的安装路径
export ZOOKEEPER_HOME=/usr/local/zookeeper
export PATH=$PATH:${JAVA_HOME}/bin:${ ZOOKEEPER_HOME }/bin
添加环境变量完成后保存退出,使用 source /etc/profile 使修改生效。
8.进入到 zookeeper 的 conf 目录,修改配置文件
cd /usr/local/zookeeper/conf
cp zoo_sample.cfg zoo.cfg vim zoo.cfg
在文档最后加入以下三行参数:
server.1=node01:2888:3888
server.2=node02:2888:3888
server.3=node03:2888:3888
注意:node01、node02、node03 为主机名
将配置文件中的 dataDir 参数值修改为:
dataDir=/usr/local/zookeeper/data
添加 dataLogDir 参数:
dataLogDir=/usr/local/zookeeper/log
9.在 zookeeper 目录下手动创建 data、log 目录
cd /usr/local/zookeeper
mkdir /usr/local/zookeeper/data
mkdir /usr/local/zookeeper/log
10.在 data 目录下创建 myid 文件并将文件内容设置为 1
cd /usr/local/zookeeper/data
touch myid
vim myid
1
保存退出 ESC --> :wq --> 回车(或者Shitt+z+z)。
11.将 zookeeper 的安装包拷贝到其它两个节点
在node02节点执行:
scp –r /bigdata/zookeeper-3.4.10 root@node02:/bigdata
在node03节点执行:
scp –r /bigdata/zookeeper-3.4.10 root@node03:/bigdata
12.在 node02 和 node03 节点分别创建 zookeeper 软链接,操作同步骤 6
13.修改 node02 和 node03 的环境变量,操作同步骤 7
14.将 node02 中的 myid 文件内容改为 2,将 node03 中的 myid 文件的内容改为 3
15.进入到 node01 的 zookeeper/bin 目录下,执行启动脚本
cd /usr/local/zookeeper/bin
zkServer.sh start
在 node02 和 node03 中执行相同操作。
16.使用 jps 命令分别查看三个节点的进程,会发现多了一个QuorumPeerMain 进程
17.分别在3个节点查看 zookeeper 状态
zkServer.sh status
如果发现三个节点有 1 个 leader 两个 follower 则说明 zookeeper成功安装并启动。
关于的实现代码示例已经上传之GitHub:
https://github.com/higminteam/bigdata/tree/master/src/main/java/bd/zookeeper
到这里我们基本了解了ZooKeeper的安装使用、工作机制,它通过一些简单好用的API,解决了分布式系统设计与开发中的难点。希望本文可以在大家理解ZooKeeper相关知识的时候做以引导或提供帮助。
大数据系列的其他文章:
大数据系列(一)之 ZooKeeper 分布式协调服务
大数据系列(二)之 hdfs 分布式文件系统详解
大数据系列(三)之 Yarn 资源调度框架详解
大数据系列(四)之 MapReduce过程及shuffle详解
大数据系列(五)之 Flume 数据传输
大数据系列(六)之 Spark 分布式计算框架
本文为学习笔记记录,仅用于学习交流参考使用。