Zookeeper全文
概述
- 一个基于观察者设计模式设计的分布式服务管理框架,负责存储和管理关心的数据,接受观察者注册,并且在数据更新时,可以通知注册观察者
- 文件系统+通知机制
- 文件系统,也就是存储服务器或其他数据的上下线信息
- 应用场景
- 统一命名服务,存储域名和对应的多个ip,类似nginx
- 统一配置管理,一个集群配置信息是一致的且同步快,各个客户端监听zookeeper的配置文件,发生改变,就进行配置更新
- 统一集群管理,掌握集群的每个节点的状态,zookeeper存储节点信息
- 服务器动态上下线,服务器上下线写入zookeeper,zookeeper通知客户端服务器的上下线
- 软负载均衡,一个服务下有多台服务器,zookeeper根据每个节点的状态,进行负载均衡
概念
- zxid,客户端每次写操作的事务id
- sid,服务器id,和myid一样
- Epoch,每个Leader任期的代号;没有leader,编号都相同,每次完成投票,都会+1
集群特点
- 一个leader,多个follower组成的集群
- 一写多读,当写请求发给follower时,会将请求转发给leader,leader写完后,再进行数据同步;半数以上节点同步完成,由响应节点给客户端回ack
- 只要有半数以上节点存活,就能正常服务,适合安装奇数台服务器
- 半数以上节点同步成功,即可返回
- 全局数据一致,每个Server保存一份相同的数据副本
- 更新请求顺序执行,同一个客户端的更新请求按照发送顺序依次执行
- 数据更新原子性,一次数据更新要么成功,要么失败
- 实时性,同步时间非常快
集群写数据
- 写请求给leader
- 写操作给follower节点
数据结构
- 与Unix文件系统类似,整体是一棵树
- 每个节点为ZNode,默认存储1MB的数据,存储简单的配置信息
- 每个ZNode,都可以通过其路径确认唯一标识
节点类型
- 持久,客户端和服务端断开连接后,不删除
- 持久化顺序编号目录节点,zookeeper会给该节点名称进行顺序编号,编号递增,未全局排序
- 短暂,断开连接后,节点删除
- 临时顺序编号目录节点,节点后面带序号
选举
- 一台服务器出现两种情况,进入leader选择
- 服务器初始化启动
- 服务器运行期间无法和leader保持连接
- 当一台机器进行选举,存在两种情况
- 集群中已经存在leader
- 集群中确实不存在leader
第一次启动
- 第一台服务器启动时,发起选举,头给自己,不够半数,那么就保持状态为LOOKING
- 第二台服务器启动,再发起一次选择,分别投给自己,并交换选票信息
- 投给myid大的机器,如果超过半数,完成选举
- 如果没超过半数,那么都为LOOKING,等下接下来的服务器启动
- 当选出leader后,后来启动的设备,都是follower
非第一次启动
- 集群中已经有leader,其他服务器会告知这台服务器leader信息,并试图连接leader,进行数据同步
- 集群中不存在leader,结合
epoch/zxid/sid
进行选举
- epoch大的胜出
- zxid大的胜出
- sid大的胜出
使用
参数解析
- 安装zookeeper之后,conf目录下的
zoo.cfg
# 通信心跳时间
tickTime=2000
# Leader 和 follower 初始化通信时间
# 10倍的心跳时间,如果没有建立,那么就建立失败
initLimit=10
# leader follower 同步通信时间,
syncLimit=5
# 数据目录
dataDir=/Users/mzx/Desktop/java/zookeeper/apache-zookeeper-3.5.9-bin/data
# 客户端连接端口
clientPort=2181
admin.serverPort=8989
#maxClientCnxns=60
#autopurge.snapRetainCount=3
#autopurge.purgeInterval=1
启动
- bin目录下
- 服务器
zkServer.sh start
- 查看状态
zkServer.sh status
- 停止
zkServer.sh stop
- 客户端
zkCli.sh
退出quit
集群安装
- 创建
zkData
,并创建myid
,并设置变好 - 修改数据存储路径,要指向
zkData
的位置 - 增加配置
server.A=B:C:D
,每个节点的配置文件下都要有全部的节点该配置
- A 表示myid的文件中的值
- B 表示服务器地址
- C 表示这个follower与leader的交换端口
- D 表示Leader挂了,需要一个端口重新进行选举
脚本
zk.sh
,并且要chmod 777 zk.sh
,变成可执行文件
# !/bin/bash
case $1 in
"start") {
for i in c1 c2 c3
do
echo --------- zookeeper $i start --------------
ssh $i "/usr/local/zookeeper/zookeeper/bin/zkServer.sh start"
done
}
;;
"stop") {
for i in c1 c2 c3
do
echo --------- zookeeper $i stop --------------
ssh $i "/usr/local/zookeeper/zookeeper/bin/zkServer.sh stop"
done
}
;;
"status") {
for i in c1 c2 c3
do
echo --------- zookeeper $i status --------------
ssh $i "/usr/local/zookeeper/zookeeper/bin/zkServer.sh status"
done
}
;;
esac
客户端使用
- 查看节点
ls /
,ls -s /
查看节点明细
// 事务id
[dubbo, services, zookeeper]cZxid = 0x0
// 创建时的毫秒值
ctime = Thu Jan 01 08:00:00 CST 1970
// 最后更新的事务
mZxid = 0x0
// 最后修改的毫秒
mtime = Thu Jan 01 08:00:00 CST 1970
// 最后更新的子节点
pZxid = 0x200
// znode子节点变化的修改次数
cversion = 7
// 数据变化号
dataVersion = 0
// 访问控制列表的变化号,权限
aclVersion = 0
// 如果是临时节点,znode拥有者的session id
ephemeralOwner = 0x0
// 数据长度
dataLength = 0
// 子节点数
numChildren = 3
- 创建
- 普通创建
create /test "i am test"
- 多目录创建
create /test/son "i am test's son"
- 带序号创建
create -s /test/mother "i am mother"
- 创建临时节点
create -e /test/student "student"
- 创建带序号临时节点
create -e -s /test/teacher "teacher"
- 获取值
get /test
、get -s /test
- 修改节点值
set /test/son "i am father"
- 删除
- 删除某个节点
delete /test/son
- 删除当前节点及所有子节点
deleteall /test
- 查看状态信息
stat /test
监听器
- 客户端向服务端进行注册,关注某个数据变化,数据变化时,服务端进行通知
- 客户端main线程,创建客户端,并且有两个线程,一个负责connect,一个负责listener
- connect线程将注册事件发送给服务端,服务端将注册的监听事件添加到列表中
- 服务端监听到有数据或路径变化,将这个消息发送给listener线程,进行处理
- 监听某个节点数据变化
get -w /test
,只注册一次监听,那么就只处理一次变化 - 监听节点数变化
ls -w /test