zk 学习笔记
一、参考资料:
zk,一般就是指 zookeeper。在 CAP 理论中,zk 主要保证 CA,并在发生网络分区错误时,仅提供只读能力。
学习书籍:《ZooKeeper 分布式过程协同技术详解》 Flavio Junqueira /Benjamin Reed
推荐阅读:Zookeeper你应该了解基础知识
二、核心内容:
2.1 主从模型
- 主从模型需要解决的三大问题:
- 主节点崩溃:
- 可以使用备份从节点,但如果想要恢复到原主节点崩溃时的状态,就要通过 zk 来获取此状态信息。
- 假崩溃:当主结点负载很高,导致的消息延迟时,备份主结点转正,此时系统就存在了两个主节点。
- 脑裂:主要指网络分区引起的、系统被分为子系统独立工作的情况。多个从节点因网络分区中断了跟主节点的通信,然后与第二主节点建立 master-slave 关系。脑裂是要被重点避免的情况。
- 从节点崩溃:
- 主结点需要检测① worker 是否崩溃;② 哪些 worker 存活以便接手崩溃 worker 的工作。
- 崩溃 worker 的任务执行进度如何,是否需要清除异常状态等。
- 通信故障:
- 跟任务的幂等性有关,如果任务是幂等的,在任务再分配时无需额外的动作。
- 但如果任务是非幂等的,任务再分配时,需要验证第一个 worker 是否已完成了工作,同时 app 需要考虑任务被多次重复执行的可能性。
- 主节点崩溃:
- zk 为了配合主从模型,所以需要具备以下能力:
- 主节点选举;
- 崩溃检测;
- 成员关系管理;
- 元数据管理;
2.2 zk 的数据模型
采用树状模型(与文件系统很像,但有所不同,zk 使用 znode 的概念):
1 | root |
注:znode 中的数据以字节数组的形式存储(使用工具序列化后存入),但可以无数据。
2.3 对外 Api
1 | create /path data ##创建一个名为/path 的结点,并包含数据 data |
注:znode 的读写都是整个结点粒度的,不存在局部读写的情况。
注 2:版本是用来阻止并行操作的不一致性。
2.4 znode 的结点分类
一般 znode 分为持久结点和临时结点两种:
- 持久结点:可以将一些数据落盘。虽然 zk 的数据一般都是在内存中,
- 临时结点:当 client 崩溃时,或者跟 zk 连接关闭时(client 与 zk 的 session 关闭时),临时结点会被删除,删除动作可主动可被动。临时结点如果拥有子节点,那么子节点也是临时结点。
- 有序结点:是另一个范畴的概念。持久结点和临时结点分别可以设置为有序的,创建有序结点时,命名会分配到唯一一个单调递增的整数序号。
2.5 notification 机制
- client 向 zk 注册需要接受通知的 znode,并对 znode 设置监视点(watch);
- 当 znode 发生变更时,client 会接收到通知,一次性的watch 发生失效,然后会继续设置下一个 watch;
- 接到通知与下一个 watch 设完之间存在时间差,此时znode 可能发生再次变更。为了获取此变更,设下一个 watch 前,client 会再读一次 znode 的状态。
2.6 zk 的 server 模式
- 通常分为独立模式和仲裁模式。
- 用人话讲:就是单机模式和集群模式。
- [重点]仲裁模式下,所有 server 都维护相同的数据树,但 client 不可能等待所有 server 完全复制数据一致后才工作,所以引入了法定人数的折中选择。
- 法定人数:保证 zk 工作的 server 最小数量。(只有满足了人数,才能保证投票立法有效)。
- 举例:5 个 server 中,法定人数为 3 个,只有当至少 3 个 zkServer 保证client 的操作生效时,client 的工作才能继续下去。而且,剩下的 2 个 server 也会最终一致。
- 法定人数采用多数方案,而且总 server 数一般为奇数,偶数系统较脆弱。
- 偶数情况举例:如果总共 4 个 server,那么法定为 3 个,系统只能允许最多 1 台 server 崩溃。
- 奇数情况举例:如果总共 5 个 server,那么法定也为 3 个,系统可以允许最多2 台 server 崩溃,系统将更加牢靠。
2.7 client 与 zk 之间的 session
- client 与 zk 的某一个 server 之间建立 Tcp 连接。
- session具有透明性。如果连接不可用时,session 会被转移到另一个 server 上。
- 此时session不会过期,只是会经历 connected - connecting - connected 的状态转换过程。
- 欲建立连接的备胎 server需要保证状态最新(具有最新的事务标识符即 zkid),否则即使此 server 可用也将不会建立连接。
- session 保障顺序性,同一个 session 中的 request 以 FIFO 顺序执行。但跨 Session 时不保证顺序性。
- session具有透明性。如果连接不可用时,session 会被转移到另一个 server 上。
2.8 多 server 间的通信
使用配置文件如下:
1 | tickTime=2000 |
注:单机模拟时因为 ip 相同,所以选用不同的 port 号,如果是集群 server,ip 地址不同时,可以选择相同的端口号。
三、server 集群和 client 搭建实战
背景:单机上模拟创建三个 server 以及一个 client。本机系统 centos6.4,zk 版本3.4.12。
配置参考《ZooKeeper 分布式过程协同技术详解》P34
安装 zk,略。
设置路径、建立文件夹、配置文件等
${PATH_TO_ZK}=/root/zookeeper
,改成你的 zookeeper 主目录路径在 zookeeper 目录下建立文件夹:”z1/data/“、”z1/data/“、”z1/data/“。
执行
1
2
3echo 1 > z1/data/myid
echo 2 > z2/data/myid
echo 3 > z3/data/myid建立文件”z1/z1.cfg”/“z2/z2.cfg”/“z3/z3.cfg”,写入配置文件:
1
2
3
4
5
6
7
8tickTime=2000
initLimit=10
syncLimit=5
dataDir=./data
clientPort=2181 ## z2/z3 中分别改为 2182、2183
server.1=127.0.0.1:2222:2223
server.2=127.0.0.1:3333:3334
server.3=127.0.0.1:4444:4445启动 z1、z2 服务器(另开一个终端),3 台 server 启动至少 2 台就可以提供服务了。
1
2
3# 启动 z1 为例
cd z1
{PATH_TO_ZK}/bin/zkServer.sh start ./z1.cfg
检查 zookeeper.out 日志,确定一个是 leader,另一个是 follower(日志中有明确的字段指示是
following
还是leading
),进入下一步。另开一个终端作为 client,执行以下命令,提示 session establishment 以及 complete on server…说明 client 与 zk 的 session 连接完成。
1
{PATH_TO_ZK}/bin/zkCli.sh -server 127.0.0.1
查看 server 的 status 及单 Server 的停止命令:
1
2
3
4
5// 在 z2 目录下:
{PATH_TO_ZK}/bin/zkServer.sh status ./z2.cfg
{PATH_TO_ZK}/bin/zkServer.sh stop ./z2.cfg如果 master 挂掉了,那么待转正的备胎会经历以下步骤:
- 备胎感知到 master 跪了,自己也会被 interrupted,然后操作一波 shutdown,进入looking 状态,然后进入新的选举;
- 备胎当选成功,更新为 leading 状态.
- 另一个落选的备胎,也会经历 looking 状态,当选举失败后进入 following 状态。
- 如果挂掉的结点刚好是与 Client 建立连接的结点,那么新连接还是会从目前存活的结点中重新建立。