导图社区 Zookeeper
Zookeeper 全助记,囊括 ZK 的应用场景、命令、部署方式、架构、原理等
编辑于2021-08-17 00:03:54Zookeeper
为分布式应用提供协调服务的开源分布式项目
概述
---工作机制--- 1. 基于观察者模式,提供分布式服务管理 2. 存储和管理大家都关心的数据 3. 接受观察者的注册,一旦观察的对象数据发生变化,Zookeeper 负责通知注册上来的观察者
特点
一主多从
一个 Leader,多个 Follower 组成的集群
Leader
投票的发起和决议,更新系统状态
Follower
1. 接收客户端请求并行客户端返回结果 2. 参与 Leader 选举的投票
半数机制
集群中半数以上节点存活,集群可用
全局数据一致
每个节点保存一份完整数据副本,Client 无论连接那个 Server 数据都一致
更新请求有序
来自同一 Client 的更新请求按其发送顺序进行
更新原子性
一次数据更新要么成功,要么失败
实时性
在一定时间范围内,Client 能读到最新数据
数据结构
类似 Unix 文件系统的树形结构,每个节点是一个 ZNode,默认可存储 1MB 数据,通过其路径唯一标识
应用场景
统一命名服务
分布式环境下,应用/服务的域名与 IP 之间的映射关系 /service/www.baidu.com - 192.168.22.13 - 192.168.22.14 - 192.168.22.15 1. 域名易记 2. 调用端通过服务名获取服务地址
统一配置管理
1. 分布式环境下,所有节点配置通过一个 ZNode 存储,可以实现快速同步 2. 监听 ZNode 可以将 ZNode 的更新应用到各节点
统一集群管理
注册临时节点并且监听节点,实现集群的在线状态监听与选举 /GroupMembers - /client1 - /client2 - /client3
应用动态上下线
客户端监听服务端注册到 ZK 的临时节点路径,可以实时获得服务器上下线变化情况 /servers -/server1 -/server2 -/server3
软负载均衡
在同一命名服务基础上加上 IP 的访问次数,客户端每次访问服务可以路由到次数少的 IP /service/register - 192.168.22.13 60 - 192.168.22.14 50 - 192.168.22.15 55
分布式锁
原理
1. 访问临界资源时,在 /locks 下创建临时顺序节点 2. 判断自己是否 /locks 下最小子节点,是则表示获取到锁,开始访问临界资源,否则监听 /locks 路径变化 3. 获得锁处理完业务后,delete 当前节点,其他访问临界资源的客户端将收到释放锁的通知,开始重复 2 的抢锁过程
问题
1. 会话连接是异步的,可以通过 CountDownLatch 处理 2. Watch 需要重复注册 3. 递归删除和创建多节点
Curator
Zookeeper 客户端框架,解决了原生 JAVA API 分布式锁的一些问题
命令行
# 启动客户端 bin/zkCli.sh
help
显示所有操作命令
ls /
查看指定节点所包含的内容
ls -w /app1
监听节点的子节点(路径监听),老版本的 ls /app1 watch WATCHER:: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/app1
ls -s /
查看指定节点数据,集 stat 结构体信息,在老版本是 ls2 / [admin, brokers, cluster, config, consumers, controller_epoch, feature, isr_change_notification,latest_producer_id_block, log_dir_event_notification, sanguo, zookeeper] cZxid = 0x0 ctime = Thu Jan 01 08:00:00 CST 1970 mZxid = 0x0 mtime = Thu Jan 01 08:00:00 CST 1970 pZxid = 0x400000001 cversion = 20 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 0 numChildren = 12
create /app1 "hello app1"
创建普通节点
create -e /app-emphemeral 8888
创建临时节点,临时节点在客户端断开后被删除
create -s /app2 888
创建有序节点 不管父节点是否存在有序子节点,创建有序节点时,顺序号都是父节点的所有子节点(包括有序和非有序)个数
get /app1
获得节点的值 hello app1
get -w /app1
监听节点的数据变化 WATCHER:: WatchedEvent state:SyncConnected type:NodeDataChanged path:/app1
get -s /app1
获取节点数据,附加次级信息
set /app1 9999
修改节点数值
delete /app1/bb
删除节点
deleteall /app1
递归删除节点,老版本的 rmr /app2
stat /app1
查看节点状态 cZxid = 0x100000018 ctime = Thu Apr 01 09:05:13 CST 2021 mZxid = 0x100000018 mtime = Thu Apr 01 09:05:13 CST 2021 pZxid = 0x100000019 cversion = 1 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 0 numChildren = 1
部署
本地模式
配置
# 1. 修改 zoo_sample.cfg 为 zoo.cfg cp /home/aurelius/software/zookeeper/conf/zoo_sample.cfg /home/aurelius/software/zookeeper/conf/zoo.cfg # 2. 修改 zoo.cfg vim zoo.cfg # 指定 dataDir 路径 dataDir=/home/aurelius/software/zookeeper/data # 3. 创建 dataDir 路径 mkdir /home/aurelius/software/zookeeper/data
案例
# 启动 ZK 服务端 bin/zkServer.sh start # 查看 ZK 进程 jps -l # 查看 ZK 状态 bin/zkServer.sh status # 启动 ZK 客户端 bin/zkCli.sh # 退出 ZK 客户端 quit # 停止 ZK 服务端 bin/zkServer.sh stop
分布式
配置
# zoo.conf 增加配置 server.1=node01:2888:3888 server.2=node02:2888:3888 server.3=node03:2888:3888 # touch dataDir/myid 1 -- 对应 zoo.conf 中 server.1,用于 Zookeeper 启动时获取 zoo.conf 中对应端口配置
案例
# 拷贝 Zookeeper 到 node02, node03 scp -r zookeeper/ root@node02:/home/aurelius/software/zookeeper/ scp -r zookeeper/ root@node03:/home/aurelius/software/zookeeper/ # 启动 Zookeeper bin/zkServer.sh start # 查看 Zookeeper 状态 bin/zkServer.sh status
配置参数
tickTime
tickTime=2000 通信心跳数,ZK 服务器心跳时间,单位毫秒 Session 最小超时时间是 2*tickTime
initLimit
initLimit=10 LF 初始通信时限,tickTime 的数量,Follower 启动时从 Leader 同步所有数据并准备对外服务的时限
syncLimit
syncLimit=5 LF 同步通信时限,tickTime 的数量,超时则 Leader 认为 Follower 已死掉,将从服务器列表删除该节点 Leader 负责与 ZK 集群所有节点通信,心跳检测节点存活状态
dataDir
数据文件目录 + 数据持久化路径 保存内存数据库快照信息,及更新的事件日志
clientPort
clientPort=2181 客户端连接服务器的端口
Server.A=B:C:D
A 是一个数字,表示是第几号服务器 B 是服务器 IP C 是这个服务器与集群中 Leader 交换信息的端口 D 是这个服务器参与 Leader 选举的通信端口
架构
选举机制
1. 投票给 id 值较大的节点 2. 获得半数以上节点的投票即可获选 Leader,选举成功前各节点保持 Looking 状态 3. 选举成功后,后来节点直接成为 Follower ---触发选举--- 1. 服务器初始化启动 2. 服务器运行其间无法和 Leader 保持连接 ---选举状态--- 1. 已经存在一个 Leader - 试图选举 Leader 时,被告知当前 Leader 信息,此时只需要与 Leader 建立连接并进行状态同步 2. 确实不存在 Leader - Epoch 大的直接胜出 - Epoch 相同,zxid 大的胜出 - zxid 相同,SID 大的胜出 Epoch - Leader 的届期,表示当前 Leader 是第几届
ZNode 类型
设置顺序标识的 ZNode 会附加一个值,即顺序号,该值单调递增,由父节点维护 在分布式系统中顺序号可以用作给事件全局排序
Persistent(default)
持久节点,客户端与服务器断开连接后,节点不会被删除
Persistent Sequential
给 ZNode 名称顺序编号
Ephemeral
临时节点,客户端与服务端断开连接后,创建的节点自动删除
Ephemeral Sequential
给 ZNode 名称进行顺序编号
stat 结构体
czxid
czxid 是 ZNode 创建事件的 ID Zookeeper 的事务 ID,也是修改 Zookeeper 状态的时间戳,因此所有事务 ID 总是有序的,后发生的一定比先发生的 zxid 大
ctime
ZNode 被创建的时间戳(ms)
mzxid
ZNode 最后更新的 zxid
mtime
ZNode 最后修改的时间戳(ms)
pzxid
ZNode 最后更新的子节点的 zxid
cversion
ZNode 子节点变化号,也是子节点修改次数
dataVersion
ZNode 数据变化号
aclVersion
ZNode 访问控制列表的变化号
ephemeralOwner
临时节点 ZNode 拥有者的 Session Id,非临时节点为 0
dataLength
ZNode 的数据长度
numChildren
ZNode 子节点数量
监听器原理
1. 客户端 main 线程创建 ZK 客户端,其包含两个线程:Listener、Connect 2. Connect 向 Zookeeper 注册监听事件 3. Zookeeper 在监听器列表添加监听事件 4. Zookeeper 监听到指定节点有数据或路径变化时,向 Listenter 发送通知 5. Listener 内部回调 process 方法 ---监听种类--- 1. get path [watch] -- 监听节点数据变化 2. ls path [watch] -- 监听节点路径变化
写数据流程
1. Client 向 Server1 发送写请求 2. Server1 如果不是 Leader,则将写请求转发给 Leader 3. Leader 将写请求广播给所有 Server 4. Server 写成功后通知 Leader,当 Leader 收到大多数 Server 的成功通知即说明写操作成功 5. Leader 通知 Server1 写成功 6. Server1 通知 Client 写成功