一、
Zookeeper概述
1.1. Zookeeper
是什么
1. zookeeper是⼀个为分布式应⽤程序提供的⼀个分布式开源协调服务框架。是Google
的
Chubby
的⼀个开源实现,是
Hadoop
和
Hbase的重要组件。主要⽤于解决分布式集群中应⽤系统的⼀致性问题。
2.
提供了基于类似
Unix
系统的⽬录节点树⽅式的数据存储。
3. 可⽤于维护和监控存储的数据的状态的变化,通过监控这些数据状态的变化,从⽽达到基于数据的集群管理
4.
提供了⼀组原语
(
机器指令
)
,提供了
java
和
c
语⾔的接⼝
- 来源
分布式系统需要服务协调组件。 配置文件共享。 某些应用需要分布式锁
- 定义
Zoo keeper :动物管理员。它可以管理:大象(hadoop)、Hbase(鲸鱼)、Flume(水虫)、Hive(蜜蜂)、Flink(松鼠)、Pig(猪)等。 zookeeper是一个分布式服务协调服务。可以将它理解为去让分布式服(Namenode、ResourceManger、Hbase、Spark、Flink、Storm等)务更好运行得服务。
1.2. Zookeeper
的特点
1.
也是⼀个分布式集群,⼀个领导者
(leader),
多个跟随者
(follower).
2.
集群中只要有半数以上的节点存活,
Zookeeper
集群就能正常服务。
3.
全局数据⼀致性:每个
server
保存⼀份相同的数据副本,
client
⽆论连接到哪个
server,
数据都是⼀致的。
4.
更新请求按顺序进行:来自同⼀个
client
的更新请求按其发送顺序依次执行
5.
数据更新的原⼦性:⼀次数据的更新要么成功,要么失败
6.
数据的实时性:在⼀定时间范围内,
client
能读到最新数据。
- 架构
注意:
1、zk的集群由多个server组成,多个一般是基数个。因为基数个好判断zk的集群是否可用。过半数的节点可用则zk的整个集群可用。 2、zk集群有且仅有一个Leader(老大),其他server全是follower(小弟)。 3、zk集群有快速选举机制。用于zk的leader宕掉之后立马从其他的follower中选举一个为leader。4、zk集群有快速数据同步协议。
1.3. Zookeeper
的数据模型
Zookeeper
的数据模型采⽤的与
Unix
⽂件系统类似的层次化的树形结构。我们可以
将其理解为⼀个具有⾼可⽤特征的⽂件系统。这个⽂件系统中没有⽂件和⽬录,⽽是
统⼀使⽤
"
节点
"(node)
的概念,称之为
znode
。
znode
既可以作为保存数据的容器
(
如
同⽂件
),
也可以作为保存其他
znode
的容器
(
如同⽬录
)
。所有的
znode
构成了⼀个层次
化的命名空间。
Zookeeper的数据模型像一个标准的树型文件系统,每一个路径都是一个唯一的。有且仅有一个根node(/)。每个节点被称为znode。 zk数据模型和树形文件系统区别: 相同:1)都是成树形;2)都用于存储数据;3)都有且仅有一个根节点。 不同:1)zk的每个节点既是目录又是文件。而linux文件系统目录就是目录,目录不能携带数据,文件就是文件。2)zk的数据量存储较小,一般每个节点存储约为字节到千字节范围。linux文件系统就能存储大量数据。zk的权限比linux要稍微多一些。
znode类型
- 临时znode节点:该类型节点生命周期随创建客户端消失而消失。
- 临时znode序列节点:除有上述功能之外,还有一个递增标识,用于避免节点已存在不能创建。
- 永久znode节点: 该类型节点生命周期是永久,手动删除及消失。
- 永久znode序列节点:除有上述功能之外,还有一个递增标识,用于避免节点已存在不能创建。
- Zookeeper 被设计用来实现协调服务(这类服务通常使用小数据文件 ) ,而不是用于大容量数据存储,因此⼀个 znode 能存储的数据被限制在 1MB 以内;- 每个 znode 都可以通过其路径唯⼀标识- zookeeper中每个节点都可以被注册一些操作的监听,类似于MySQL的触发器。
1.
统⼀配置管理
2.
统⼀集群管理
3.
服务器节点动态上下线感知
4.
软负载均衡等
5.
分布式锁
6.
分布式队列
1.5. zookeeper
的作⽤
1.
负责提供阶段的监听注册作⽤
2.
负责接收⽤户的⼼跳
,
进⾏通信
,
感知⽤户的状态
3.
负责为⽤户提供注册
,
查找信息
4.
负责负载均衡
注意
:
1.
如果现在再新增⼀个服务器
,
要先完成在
zookeeper
中的注册
,
这时我就知道可以有
⼀个新的服务器可⽤
,
分配任务时进⾏较平均分配
(
负载均衡
)
2.zookeeper
可以单机版
,
但是他的压⼒也很⼤
,
所以⼀般
zookeeper
也是⼀个分布式
的
二、Zookeeper
的安装部署
2.1
环境变量的配置
1
.
将
zookeeper-3.4.10.tar.gz
上传到
/root
中
2
.
解压
[root@hostname ~]
# tar -zxvf zookeeper-3.4.10.tar.gz -C
/opt/apps/
3
.
更名
zookeeper
[root@hostname ~]
# cd /opt/apps/
[root@hostname local]
# mv zookeeper-3.4.10 zookeeper
4
.
配置环境变量
[root@hostname local]
# vi /etc/profile
.........
省略
......
export
ZOOKEEPER_HOME
=
/opt/apps/zookeeper
export
PATH
=
$ZOOKEEPER_HOME
/bin:
$PATH
5
.
使当前会话⽣效
[root@hostname local]
# source /etc/profile
6
.
检查如下:
如果只检查环境变量是否配置成功,只需要使⽤
tab
键进⾏补全
zk
,是否
zookeeper
的
相关脚本提示即可。
注意:第七步,只能是运⾏
zookeeper
服务后,才能这样查看。
7
.
查看
zookeeper
的版本号
[root@hostname local]
# echo stat | nc localhost 2181
2.2 独⽴模式(
standalone模式
)的安装
1
复制出⼀个
zoo.cfg
⽂件
(
有⼀个样本
zoo_sample.cfg)
[root@hostname local]
# cd zookeeper/
[root@hostname zookeeper]
# cd conf/ #
进⼊zookeeper的
conf
⽬录
[root@hostname conf]
# cp zoo_sample.cfg zoo.cfg #复制出zoo.cfg
⽂件
2
修改
zoo.cfg
⽂件
[root@hostname conf]
# vi zoo.cfg
tickTime
=
2000
#
定义的时间单元
(
单位毫秒
),下⾯的两个值都是tickTime
的倍数。
initLimit
=
10
#follower连接并同步leader
的初始化连接时间。
syncLimit
=
5
#⼼跳机制的时间(
正常情况下的请求和应答的时间
)
dataDir
=
/opt/apps/zookeeper/zkData
#
修改
zookeeper数据的存储路径
clientPort
=
2181
#客户端连接服务器的port
2.3
启动测试
1
在本地上开启
server
[root@hostname ~]
# zkServer.sh start
2
使⽤客户端连接服务
[root@hostname ~]
# zkCli.sh [-server] [host]
3
进⾏⼀些命令的操作
[zk: localhost:2181(CONNECTED)
0
] help
4
客户端退出
[zk: localhost:2181(CONNECTED)
1
] quit/close
5
服务器退出
[root@hostname ~]
# zkServer.sh stop
2.4
集群模式的配置
1
Zookeeper
的服务进程布局
hostname01 QuorumPeerMain
hostname02 QuorumPeerMain
hostname03 QuorumPeerMain
2
修改
zoo.cfg
⽂件
[root@hostname local]# cd ./zookeeper/conf/
[root@hostname conf]# cp zoo_sample.cfg zoo.cfg #复制出zoo.cfg⽂件
[root@hostname conf]# vi zoo.cfg
tickTime=2000 # 定义的时间单元(单位毫秒),下⾯的两个值都是tickTime的倍数。
initLimit=10 # follower连接并同步leader的初始化连接时间。
syncLimit=5 #⼼跳机制的时间(正常情况下的请求和应答的时间)
dataDir=/opt/apps/zookeeper/zkData #修改zookeeper的存储路径,zkData⽬录⼀会要创建出来
clientPort=2181 #客户端连接服务器的port
server.1=hostname01:2888:3888 # 添加三个服务器节点
server.2=hostname02:2888:3888
server.3=hostname03:2888:3888
解析Server.id=ip:port1:port2
id: 服务器的id号,对应zkData/myid⽂件内的数字
ip: 服务器的ip地址
port1: follower与leader交互的port
port2: 选举期间使⽤的port
注意:此配置⽂件中,不⽀持汉字注释
3
在
$ZK_HOME/zkData/
⽬录下添加
myid
⽂件,内容为
server
的
id
号
[root@hostname conf]# cd ..
[root@hostname zookeeper]# mkdir zkData
[root@hostname zookeeper]# cd zkData
[root@hostname zkData]# echo "1" > myid
4
搭建其他两个
server
节点的环境
1
)使⽤
scp
命令将zookeeper环境 复制到hostname02和hostname03中
[root@hostname zkData]
# cd /opt/apps
[root@hostname apps]
# scp -r zookeeper hostname
02:/opt/apps
[root@hostname apps
# scp -r zookeeper hostname
03:/opt/apps
2
) 使⽤
scp
命令拷⻉
/etc/profile
到两台机器上
(
别忘记
source
⼀下
)
[root@hostname apps]
# scp /etc/profile hostname
02:/etc/
[root@hostname apps]
# scp /etc/profile hostname
03:/etc/
3) 修改hostname02的
myid
⽂件的内容为
2
[root@hostname ~]
# ssh hostname02
[root@hostname ~]
# echo "2" > /opt/apps/zookeeper/zkData/myid
4)
修改
qianfeng03
的
myid
⽂件的内容为
3
[root@hostname ~]
# ssh hostname03
[root@hostname ~]
# echo "3" > /opt/apps/zookeeper/zkData/myid
2.5
启动
zookeeper
1
)三台机器上都启动
zookeeper
的服务
(
注意保证防⽕墙是关闭的
)
[root@hostname ~]
# zkServer.sh start
再查看⼀下状态
[root@hostname ~]
# zkServer.sh status
2
) 启动客户端的操作:
zkCli.sh [-server] [ ip:port]
reg:
[root@hostname ~]
# zkCli.sh #
启动
客户端,连接本地服务进程
[root@hostname ~]
# zkCli.sh -server hostname02:2181 #
启动客户端,连接hostname02上的服务进程
3
)连接成功后:
输⼊
help,
查看所有指令,如下图
zookeeper的shell操作1. ls -- 查看某个⽬录包含的所有⽂件2. ls2 -- 查看某个⽬录包含的所有⽂件,与 ls 不同的是它查看到 time 、version等信息3. create -- 创建 znode ,并设置初始内容,例如:[zk: 47.0.0.1:2181(CONNECTED) 1] create /test "test"Created /test4. get -- 获取 znode 的数据5. set -- 修改 znode 内容6. delete -- 删除 znode7. quit -- 退出客户端8. help -- 帮助命令
2.6
节点类型
2.6.1
节点状态
1. ephemeral(
短暂
)
:客户端和服务器断开后,创建的节点⾃⼰删除。
2. persistent(
持久
)
:客户端和服务器断开后,创建的节点不删除
(
默认情况
)
2.6.2
节点类型
1. persistent :
断开连接后,该节点依旧存在
2. persistent_sequential :断开连接后,该节点依旧存在。节点名进⾏顺序编号
3. ephemeral :
断开连接后,该节点⾃动删除
4. ephemeral_sequential :
断开连接后,该节点⾃动删除。节点名进⾏顺序编号
三、
Zookeeper
的⼯作原理
3
.1
选举制度
3.1.1
说明
- 1.
基于节点在半数以上才能正常服务的要求,
Zookeeper
适合装在奇数台机器。
- 2. Zookeeper
没有在配置⽂件中指定
leader
和
follower
,⽽是使⽤算法
(Paxos)
在内部通过选举机制来选择⼀个节点为
leader
,其他节点为
follower
。
3.1
.2
开机启动时的选举过程
假设有五台服务器组成的
zookeeper
集群,它们的
id
从
1-5
,同时它们都是最新启
动的,也就是没有历史数据,在存放数据量这⼀点上,都是⼀样的。假设这些服务器
依序启动,来看看会发⽣什么。
1. 服务器 1 启动此时只有它⼀台服务器启动了,它发出去的投票信息没有任何响应,所以它的选举状态⼀直是 LOOKING 状态。2. 服务器 2 启动它与最开始启动的服务器 1 进⾏通信,互相交换⾃⼰的选举结果,由于两者都没有历史数据,所以 id 值较⼤的服务器 2 胜出,但是由于没有达到超过半数以上的服务器都同意选举它 ( 这个例⼦中的半数以上是 3) ,所以服务器 1 、 2 还是继续保持 LOOKING 状态。3. 服务器 3 启动根据前⾯的理论分析,服务器 3 成为服务器 1 、 2 、 3 中的⽼⼤,⽽与上⾯不同的是,此时有三台服务器选举了它,所以它成为了这次选举的 leader 。4. 服务器 4 启动根据前⾯的分析,理论上服务器 4 应该是服务器 1 、 2 、 3 、 4 中最⼤的,但是由于前⾯已经有半数以上的服务器选举了服务器 3 ,所以它只能接收当⼩弟的命了。5. 服务器 5 启动同 4 ⼀样当⼩弟
3.1.3.
为什么需要
leader
选举:
Leader
选举是保证分布式数据⼀致性的关键所在
.
当
Zookeeper
集群中的⼀台服务器出现以下两种情况之⼀时,需要进⼊
Leader
选
举。
(1)
服务器初始化启动。
(2)
服务器运⾏期间⽆法和
Leader
保持连接。
原则
:
默认半数以上的机器同意
,
当前的节点就是
leader
默认半数以上的机器存活
,zookeeper
集群就能对外提供服务
3.2
选举制度中的四个概念
Leader:Zookeeper 集群⼯作的核⼼。事务请求(写操作) 的唯⼀调度和处理者,保证集群事务处理的顺序性;集群内部各个服务器的调度者。对于 create , setData , delete 等有写操作的请求,需要统⼀转发给 leader处理, leader 需要决定编号、执⾏操作,这个过程称为⼀个事务。Follower:处理客户端⾮事务(读操作) 请求,转发事务请求给 Leader ;参与集群 Leader 选举投票 2n-1 台可以做集群投票。此外,针对访问量⽐较⼤的 zookeeper 集群, 还可新增观察者⻆⾊。Observer:观察者⻆⾊,观察 Zookeeper 集群的最新状态变化并将这些状态同步过来,其对于⾮事务请求可以进⾏独⽴处理,对于事务请求,则会转发给 Leader 服务器进⾏处理。不会参与任何形式的投票只提供⾮事务服务,通常⽤于在不影响集群事务处理能⼒的前提下提升集群的⾮事务处理能⼒。- serverid: 服务器 id⽐如有三台服务器,编号分别为 1 , 2 , 3 。编号越⼤在选择算法中的权重越⼤- zxid: 数据 id服务器中存放的最⼤数据 ID 。值越⼤说明数据越新,在选举算法中的权重越⼤- Epoch: 逻辑时钟也可以称之为每个服务器参加投票的次数。同⼀轮投票过程中的逻辑次数优先级: Epoch > zxid >serverid- Server 状态:选举状态- LOOKING :竞选状态- FOLLOWING: 随从状态,同步 leader 状态,参与选票- OBSERVING: 观察状态,同步 leader 状态,不参与选票- LEADER :领导者状态
3.3 Zookeeper
的监听原理
图解:
1. ⾸先要有⼀个 main() 线程2. 在 main 线程中创建 Zookeeper 客户端, 这时就会创建两个线程, ⼀个负责⽹络连接通信 (connet), ⼀个负责监听 (listener) 。3. 通过 connect 线程将注册的监听事件发送给 Zookeeper 。4. 在 Zookeeper 的注册监听器列表中将注册的监听事件添加到列表中。5. Zookeeper 监听到有数据或路径变化, 就会将这个消息发送给 listener 线程。6. listener 线程内部调⽤了 process () ⽅法。
⽤途
:
1. 监听节点数据的变化 : get /path watch2. 监听⼦节点增减的变化 : ls /path watch
3.4
写数据流程
参考上图:
1. Client 向 Zookeeper 的 server1 上写数据,发送⼀个写请求2. 如果 server1 不是 leader, 那么 server1 会把请求进⼀步转发给 leader 。3. 这个 leader 会将写请求⼴播给所有 server 。4. 各个 Server 写成功后就会通知 leader 。5. 当 leader 收到半数以上的 server 写成功的通知,就说明数据写成功了。写成功后,leader 会告诉 server1 数据写成功了。6. server1 会进⼀步通知 Client 数据写成功了。这时就认为整个写操作成功。