概念
基于观察者模式设计的分布式服务管理框架,负责存储和管理大家都关心的数据,接受观察者的注册,并在数据变更时通知注册的观察者们做出相应行动。【文件系统 + 通知机制】
特点
- 一个领导者 (Leader),多个跟随者 (Follower)组成的集群
- 半数以上节点存活就能正常服务,适合奇数台服务
- 全局数据一致
- 有序执行,来自同一个 Client 的更新请求按其发送顺序依次执行
- 数据更新原子性
- 实时性,同步速度块
数据结构
数据模型整体为一棵树。节点为 ZNode,默认能存储 1MB 的数据,通过其路径位移标识。
应用场景
- 统一命名服务
- 统一配置管理
- 集群配置一致
- 配置修改同步
- 统一集群管理
- 监控节点状态(监测其他节点)
- 同步节点状态(被其他节点监测)
- 服务器动态上下线
- 软负载均衡
参数配置
tickTime-----------通信心跳时间/ms
initLimit----------Leader-Follower初始通信时限/s
syncLimit ---------Leader-Follower同步通信时限/s
dateDir------------Zookeeper数据保存路径
clientPort---------客户连接端口
集群
集群启动
- 安装文件路径下创建 zkData
- zkData 目录下创建 myid,并添加对应服务器编号(唯一)
- zoo.cfg 文件中增加集群配置 server.A = B : C : D
- A:数字,服务器编号
- B:服务器地址
- C:Leader-Follower 信息交换端口
- D:服务器选举端口
选举机制
初次选举
- 启动后投票自己
- 票数不满一半则保持 LOOKING 状态
- 交换选票,把票投给 myid 更大的服务器
- 票数满足则更改状态为 FOLLOWING / LEADING
- 已存在 Leader 后,新创建的服务会跟投 Leader,并修改状态
Client
- SID:服务器ID,和 myid一致
- ZXID:事务ID,标识一次服务器状态的变更
- Epoch:每个 Leader 任期的代号。没有 Leader 使用逻辑时钟值
再次选举
Leader 选举条件:
- 服务器启动时进入 Leader 选举
- 服务器运行期间无法和 Leader 保持连接时进入选举
进入选举流程后,集群状态:
- 集群中存在 Leader ==> 和 Leader 建立连接并同步
- 集群中不存在 Leader ==> 进入 Leader 选举
选举关注 (Epoch, ZXID, SID) ,按照顺序对应值更大的服务器胜出。
批量操作脚本示例
#! /bin/bash
case $1 in
"start"){
for i in
do
ssh $i "/path/bin/zkServer.sh start"
done
}
;;
"stop"){
for i in
do
ssh $i "/path/bin/zkServer.sh stop"
done
}
;;
"status"){
for i in
do
ssh $i "/path/bin/zkServer.sh status"
done
}
;;
esac
客户端
客户端命令操作
命令基本语法 | 功能描述 |
help | 帮助 |
ls path | ls 查看当前 znode 的子节点 [可监听] -w 监听子节点变化 -s 附加次级信息 |
create | 普通创建 -s 含有序列 -e 临时(重启、超时消失) |
get path | 获得节点的值 -w 监听节点内容变化 -s 附加次级信息 |
set | 设置节点具体值 |
stat | 查看节点状态 |
delete | 删除节点 |
deleteall | 递归删除节点 |
ZNode 节点数据信息
czxid --------- 创建节点的事务 id
ctime --------- znode 被创建的毫秒数(从 1970 年开始)
mzxid --------- znode 最后更新的事务 zxid
mtime --------- znode 最后修改的毫秒数(从 1970 年开始)
pZxid --------- znode 最后更新的子节点 zxid
cversion ------ znode 子节点变化号,znode 子节点修改次数
dataversion --- znode 数据变化号
aclVersion ---- znode 访问控制列表的变化号
ephemeralOwner 临时节点 -> znode 拥有者的 session id。非临时节点 -> 0
dataLength ---- znode 的数据长度
numChildren --- znode 子节点数量
ZNode 节点类型
- 持久 Persistent:服务器和客户端断开连接后,创建的节点不删除
- 短暂 Ephemeral:服务器和客户端断开连接后,创建的节点自删除
- 持久化目录节点:客户端与 Zookeeper 断开连接后该节点依旧存在
- 持久化顺序编号目录节点:带序号ZNode 名称后附加一个顺序标识,单调递增由父节点维护
- 临时目录节点:客户端与 Zookeeper 断开连接后该节点被删除
- 临时顺序编号目录节点:Zookeeper 给该节点名称进行顺序编号
监听器原理

- main() 线程
- main 中创建 Zk客户端,会产生两个新线程,负责监听和连接
- 通过 connect 将注册的监听事件发送给 Zookeeper
- 在 Zookeeper 的注册监听表中将注册的监听事件添加到列表中
- Zookeeper 监听到数据或路径变化,将信息发送给 Listener 线程
- Listener 线程内部调用处理方法
直接操作指令
get -w path ---------- 监听节点数据变化
ls -w path ---------- 监听节点的子节点变化(注册一次生效一次)
// 客户端 API 操作示例 // ZooKeeper 构造方法 Zookeeper zkCli = new ZooKeeper(String connectString, int sessionTimeout, Watcher watcher); // 创建节点 zkCli.create(String path, Byte[] data, List<ACL> acl, CreateMode createMode); /** * 获取子节点并监听节点变化 * @return List<String> */ zkCli.getChildren(String path, Watcher watcher); /** * 判断节点是否存在 * @return Stat */ zkCli.exist(String path, Watcher watcher);
客户端写数据流程
发送给 Leader 节点

发送给 Follower 节点
