一、概述
ZooKeeper 是 Apache 基金会开发的一款分布式协调服务,专为解决分布式系统中的一致性、同步、配置管理等核心问题而设计。
1.1 数据模型与应用场景
1.1.1 数据模型
(1)ZooKeeper 的数据结构类似 Unix 文件系统,是一个树形结构(ZNode Tree)。
(2)每个节点称为 ZNode,可以存储数据(最大 1MB)并挂载子节点。
(3)ZNode 分为四类,主要基于持久性和顺序性两个维度划分。
类型 | 持久性 | 自动生成序列号 | 是否支持子节点 |
持久节点 | 会话结束后保留 | × | ✔ |
持节顺序节点 | 会话结束后保留 | ✔ | ✔ |
临时节点 | 会话结束后删除 | × | × |
临时顺序节点 | 会话结束后删除 | ✔ | × |
1.1.2 应用场景
(1)统一命名服务
(2)统一配置管理
(3)统一集群管理
(4)感知节点上下线
1.2 zookeeper特点
- Zookeeper:一个领导者(Leader),多个跟随者(Follower)组成的集群。
- 集群中只要有半数以上节点存活,Zookeeper集群就能正常服务。所以Zookeeper适合安装奇数台服务器。
- 全局数据一致:每个Server保存一份相同的数据副本,Client无论连接到哪个Server,数据都是一致的。
- 更新请求顺序执行,来自同一个Client的更新请求按其发送顺序依次执行。
- 数据更新原子性,一次数据更新要么成功,要么失败。
- 实时性,在一定时间范围内,Client能读到最新数据。
二、集群部署
2.1 下载地址
Apache ZooKeeperhttps://zookeeper.apache.org/documentation.html
2.2 部署
[root@hadoop101 software]# cd ../module/
[root@hadoop101 module]# ls
apache-zookeeper-3.5.7-bin jdk-1.8
[root@hadoop101 module]# mv apache-zookeeper-3.5.7-bin/ zookeeper-3.5.7
[root@hadoop101 module]# ls
jdk-1.8 zookeeper-3.5.7
编辑同步脚本
mkdir /root/bin
vim /root/bin/xsync.sh
—————————————————————————–
#!/bin/bash
if [ $# -lt 1 ]
then
echo No Enough Argument!
exit
fi
for host in hadoop101 hadoop102 hadoop103 hadoop104
do
echo ==================================host=====================================
for file in $@
do
if [ -e $file ]
then
pdir=$(cd -P $(dirname $file); pwd)
fname=$(basename $file)
ssh $host "mkdir -p $pdir"
echo $host $pdir $fname
echo rsync -av $pdir/$fname $host:$pdir
rsync -av $pdir/$fname $host:$pdir
else
echo $file does not exists!
fi
done
done
——————————————————————————
chmod 775 /root/bin/xsync.sh
创建数据存储目录
[root@hadoop101 zookeeper]# mkdir -p /data/zookeeper
[root@hadoop101 zookeeper]# vim /data/zookeeper/myid
[root@hadoop101 zookeeper]# echo 1 > /data/zookeeper/myid
[root@hadoop101 zookeeper]# xsync.sh /data/zookeeper/myid
————————————————————-
在其他两台机器上执行
[root@hadoop102 zookeeper]# echo 2 > /data/zookeeper/myid
[root@hadoop102 /]# cd opt/module/
[root@hadoop102 module]# ls
jdk-1.8 zookeeper-3.5.7
[root@hadoop103 zookeeper]# echo 3 > /data/zookeeper/myid
修改配置文件并分发
[root@hadoop101 conf]# cd /opt/module/zookeeper-3.5.7/conf/
[root@hadoop101 conf]# mv ./zoo_sample.cfg zoo.cfg
[root@hadoop101 conf]# vim zoo.cfg
—————————————————————————————–
# The number of milliseconds of each tick
# 通信心跳时间,Zookeeper服务器与客户端心跳时间,单位毫秒
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
# Leader和Follower初始连接时能容忍的最多心跳数(tickTime的数量)
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
# Leader和Follower之间通信时间如果超过syncLimit * tickTime,Leader认为Follwer死掉,从服务器列表中删除Follwer。
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
dataDir=/data/zookeeper
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
# server.A=B:C:D
# A是一个数字,表示这第几号服务器;
# 集群模式下配置一个文件myid,这个文件在dataDir目录下,这个文件里面有一数据就是A的值,Zookeeper启动时读取此文件,拿到里面的数据与zoo.cfg里面的配置信息比较从而判断到底是哪个server。
# B是这个服务器的地址;
# C是这个服务器Follower与集群中的Leader服务器交换信息的端口;
# D是万一集群中的Leader服务器挂了,需要一个端口来重新进行选举,选出一个新的leader,而这个端口就是用来执行选举时服务器相互通信的端口。
server.1=hadoop101:2888:3888
server.2=hadoop102:2888:3888
server.3=hadoop103:2888:3888
—————————————————————————————–
[root@hadoop101 zookeeper]# xsync.sh /opt/module/zookeeper-3.5.7
编写集群群起脚本
[root@hadoop101 zookeeper]# vim /root/bin/zk.sh
————————————————————————-
#!/bin/bash
case $1 in
"start"){
for i in hadoop101 hadoop102 hadoop103
do
echo —————————zookeeper $i 启动———————————-
ssh $i /opt/module/zookeeper-3.5.7/bin/zkServer.sh start
done
};;
"stop"){
for i in hadoop101 hadoop102 hadoop103
do
echo —————————zookeeper $i 停止———————————-
ssh $i /opt/module/zookeeper-3.5.7/bin/zkServer.sh stop
done
};;
"status"){
for i in hadoop101 hadoop102 hadoop103
do
echo —————————zookeeper $i 状态———————————-
ssh $i /opt/module/zookeeper-3.5.7/bin/zkServer.sh status
done
};;
esac
—————————————————————————-
[root@hadoop101 zookeeper]# chmod 775 /root/bin/zk.sh
启动集群
[root@hadoop101 bin]# zk.sh start
—————————zookeeper hadoop101 启动———————————-
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Starting zookeeper … STARTED
—————————zookeeper hadoop102 启动———————————-
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Starting zookeeper … STARTED
—————————zookeeper hadoop103 启动———————————-
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Starting zookeeper … STARTED
[root@hadoop101 bin]# zk.sh status
—————————zookeeper hadoop101 状态———————————-
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: follower
—————————zookeeper hadoop102 状态———————————-
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: leader
—————————zookeeper hadoop103 状态———————————-
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: follower
三、选举机制
为什么要进行Leader选举? Leader 主要作用是保证分布式数据一致性,即每个节点的存储的数据同步。遇到以下两种情况需要进行Leader选举
-
服务器初始化启动
-
服务器运行期间无法和Leader保持连接,Leader节点崩溃,逻辑时钟崩溃。
SID:服务器ID。用来唯一标识一台ZooKeeper集群中的机器,每台机器不能重复,和myid一致。 ZXID:事务ID。ZXID是一个事务ID,用来标识一次服务器状态的变更。在某一时刻,集群中的每台机器的ZXID值不一定完全一致,这和ZooKeeper服务器对于客户端“更新请求”的处理逻辑有关。 Epoch:每个Leader任期的代号。没有Leader时同一轮投票过程中的逻辑时钟值是相同的。每投完一次票这个数据就会增加。
每个服务的投票为(SID,ZXID,Epoch)
选举Leader规则: EPOCH大的直接胜出;EPOCH相同,事务id大的胜出;事务id相同,服务器id大的胜出
3.1 第一次启动
/opt/module/jdk-1.8/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Starting zookeeper … STARTED
####以下内容可以看到,zk进程已经启动,但他没有成为leader
[root@hadoop101 bin]# zk.sh status
—————————zookeeper hadoop101 状态———————————-
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Error contacting service. It is probably not running.
—————————zookeeper hadoop102 状态———————————-
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Error contacting service. It is probably not running.
—————————zookeeper hadoop103 状态———————————-
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Error contacting service. It is probably not running.
[root@hadoop101 bin]# jps
19809 Jps
19709 QuorumPeerMain
Server2启动,再发起一次选举。Server1和2分别投自己一票并交换选票信息:此时Server1发现Server2的myid比自己目前投票推举的(Server1)大,更改选票为推举Server2。此时Server1票数0票,Server2票数2票,达到半数以上结果,Server2当选Leader。Server1更改状态为FOLLOWER,Server2更改状态为LEADER;
[root@hadoop102 conf]# /opt/module/zookeeper-3.5.7/bin/zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Starting zookeeper … STARTED
You have mail in /var/spool/mail/root
————————————————————————
[root@hadoop101 bin]# zk.sh status
—————————zookeeper hadoop101 状态———————————-
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: follower
—————————zookeeper hadoop102 状态———————————-
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: leader
—————————zookeeper hadoop103 状态———————————-
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Error contacting service. It is probably not running.
Server3启动,发起一次选举。此时Server1,2已经不是LOOKING状态,不会更改选票信息。交换选票信息结果:Server2为2票,Server3为1票。此时Server3服从多数,更改选票信息为Server2,并更改状态为FOLLOWER;
[root@hadoop103 zookeeper]# /opt/module/zookeeper-3.5.7/bin/zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Starting zookeeper … STARTED
—————————————————————————-
[root@hadoop101 bin]# zk.sh status
—————————zookeeper hadoop101 状态———————————-
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: follower
—————————zookeeper hadoop102 状态———————————-
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: leader
—————————zookeeper hadoop103 状态———————————-
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: follower
3.2 非第一次启动
而当一台机器进入Leader选举流程时,当前集群也可能会处于以下两种状态: • 集群中本来就已经存在一个Leader。 对于第一种已经存在Leader的情况,机器试图去选举Leader时,会被告知当前服务器的Leader信息,对于该机器来说,仅仅需要和Leader机器建立连 接,并进行状态同步即可。 • 集群中确实不存在Leader。 假设ZooKeeper由3台服务器组成,SID分别为1、2、3;ZXID分别为8、8、7,并且此时SID为2的服务是Leader。某一时刻,服务2出现故障,因此开始进行Leader选举。服务1由于事务id,胜出。
评论前必须登录!
注册