应用
Zookeeper写入是强一致性读取是顺序一致性
常见cli命令
zookeeper.apache.org/doc/r3.8.0/…
| 命令基本语法 | 功能描述 | |
|---|---|---|
| help | 显示所有操作命令 | |
| ls [-s] [-w] [-R] path | 使用 ls 命令来查看当前 znode 的子节点 [可监听]-w: 监听子节点变化-s: 节点状态信息(时间戳、版本号、数据大小等)-R: 表示递归的获取 | |
| create [-s] [-e] [-c] [-t ttl] path [data] [acl] | 创建节点-s : 创建有序节点。-e : 创建临时节点。-c : 创建一个容器节点。t ttl] : 创建一个TTL节点, -t 时间(单位毫秒)。data:节点的数据,可选,如果不使用时,节点数据就为null。acl:访问控制 | |
| get [-s] [-w] path | 获取节点数据信息-s: 节点状态信息(时间戳、版本号、数据大小等)-w: 监听节点变化 | |
| set [-s] [-v version] path data | 设置节点数据-s:表示节点为顺序节点-v: 指定版本号 | |
| getAcl [-s] path | 获取节点的访问控制信息-s: 节点状态信息(时间戳、版本号、数据大小等) | |
| setAcl [-s] [-v version] [-R] path acl | 设置节点的访问控制列表-s:节点状态信息(时间戳、版本号、数据大小等)-v:指定版本号-R:递归的设置 | |
| stat [-w] path | 查看节点状态信息 | |
| delete [-v version] path | 删除某一节点,只能删除无子节点的节点。-v: 表示节点版本号 | |
| deleteall path | 递归的删除某一节点及其子节点 | |
| setquota -n | -b val path | 对节点增加限制n:表示子节点的最大个数b:数据值的最大长度,-1表示无限制 |
ZK数据结构
树形结构,每个节点可以存储数据但不适合存储大量数据,最大1M
ZK节点类型
- 持久节点:断开连接不会丢失
- 临时节点:断开连接丢失节点
- 持久顺序节点:有序的持久节点
- 临时顺序节点:有序的临时节点
- container节点(3.5.3新增)
- TTL节点(默认禁用)
ZK节点状态信息
- cZxid :Znode创建的事务id。
- ctime:节点创建时的时间戳。
- mZxid :Znode被修改的事务id,即每次对znode的修改都会更新mZxid。对于zk来说,每次的变化都会产生一个唯一的事务id,zxid(ZooKeeper Transaction Id),通过zxid,可以确定更新操作的先后顺序。例如,如果zxid1小于zxid2,说明zxid1 操作先于zxid2发生,zxid对于整个zk都是唯一的,即使操作的是不同的znode。
- pZxid: 表示该节点的子节点列表最后一次修改的事务ID,添加子节点或删除子节点就会影响子节点列表,但是修改子节点的数据内容则不影响该ID(注意: 只有子节点列表变更了才会变更pzxid,子节点内容变更不会影响pzxid)
- mtime:节点最新一次更新发生时的时间戳.
- cversion :子节点的版本号。当znode的子节点有变化时,cversion 的值就会增加1。
- dataVersion:数据版本号,每次对节点进行set操作,dataVersion的值都会增加1(即使设置的是相同的数据),可有效避免了数据更新时出现的先后顺序问题。
- ephemeralOwner:如果该节点为临时节点, ephemeralOwner值表示与该节点绑定的session id。如果不是, ephemeralOwner值为0(持久节点)。
- dataLength : 数据的长度
- numChildren :子节点的数量(只统计直接子节点的数量)
监听通知(watcher)机制
- 一个Watch事件是一个一次性的触发器,当被设置了Watch的数据发生了改变的
时候,则服务器将这个改变发送给设置了Watch的客户端,以便通知它们。
- Zookeeper采用了 Watcher机制实现数据的发布订阅功能,多个订阅者可同时
监听某一特定主题对象,当该主题对象的自身状态发生变化时例如节点内容改变、节
点下的子节点列表改变等,会实时、主动通知所有订阅者。
- watcher机制事件上与观察者模式类似,也可看作是一种观察者模式在分布式场
景下的实现方式。
watcher的过程
- 客户端向服务端注册watcher
- 服务端事件发生触发watcher
- 客户端回调watcher得到触发事件情况
注意:Zookeeper中的watch机制,必须客户端先去服务端注册监听,这样事件发送才会触
发监听,通知给客户端。
支持的事件类型:
None: 连接建立事件
NodeCreated: 节点创建
NodeDeleted: 节点删除
NodeDataChanged:节点数据变化
NodeChildrenChanged:子节点列表变化
DataWatchRemoved:节点监听被移除
ChildWatchRemoved:子节点监听被移除
| 特性 | 说明 |
|---|---|
| 一次性触发 | watcher是一次性的,一旦被触发就会移除,再次使用时需要重新注册 |
| 客户端顺序回调 | watcher回调是顺序串行执行的,只有回调后客户端才能看到最新的数据状态。一个watcher回调逻辑不应该太多,以免影响别的watcher执行 |
| 轻量级 | WatchEvent是最小的通信单位,结构上只包含通知状态、事件类型和节点路径,并不会告诉数据节点变化前后的具体内容 |
| 时效性 | watcher只有在当前session彻底失效时才会无效,若在session有效期内快速重连成功,则watcher依然存在,仍可接收到通知; |
应用场景
- 使用临时节点解决分布式锁
- 通过顺序节点生成分布式ID
- 注册中心
- 配置中心
- 集群管理
ZookeeperLeader选举原理
zookeeper的leader选举存在两个阶段,一个是服务器启动时leader选举,另一个是运行过程中leader服务器宕。
几个重要的参数:
- 服务器 ID(myid):编号越大在选举算法中权重越大
- 事务 ID(zxid):值越大说明数据越新,权重越大
- 逻辑时钟(epoch-logicalclock):同一轮投票过程中的逻辑时钟值是相同的,每投完一次值会增加
选举状态:
- LOOKING: 竞选状态
- FOLLOWING: 随从状态,同步 leader 状态,参与投票
- OBSERVING: 观察状态,同步 leader 状态,不参与投票
- LEADING: 领导者状态
服务器启动时的 leader 选举
每个节点启动的时候都 LOOKING 观望状态,接下来就开始进行选举主流程。这里选取三台机器组成的集群为例。第一台服务器 server1启动时,无法进行 leader 选举,当第二台服务器 server2 启动时,两台机器可以相互通信,进入 leader 选举过程。
- 每台 server 发出一个投票,由于是初始情况,server1 和 server2 都将自己作为 leader 服务器进行投票,每次投票包含所推举的服务器myid、zxid、epoch,使用(myid,zxid)表示,此时 server1 投票为(1,0),server2 投票为(2,0),然后将各自投票发送给集群中其他机器。
- 接收来自各个服务器的投票。集群中的每个服务器收到投票后,首先判断该投票的有效性,如检查是否是本轮投票(epoch)、是否来自 LOOKING 状态的服务器。
- 分别处理投票。针对每一次投票,服务器都需要将其他服务器的投票和自己的投票进行对比,对比规则如下:
-
- a. 优先比较 epoch
- b. 检查 zxid,zxid 比较大的服务器优先作为 leader
- c. 如果 zxid 相同,那么就比较 myid,myid 较大的服务器作为 leader 服务器
- 统计投票。每次投票后,服务器统计投票信息,判断是都有过半机器接收到相同的投票信息。server1、server2 都统计出集群中有两台机器接受了(2,0)的投票信息,此时已经选出了 server2 为 leader 节点。
- 改变服务器状态。一旦确定了 leader,每个服务器响应更新自己的状态,如果是 follower,那么就变更为 FOLLOWING,如果是 Leader,变更为LEADING。此时 server3继续启动,直接加入变更自己为 FOLLOWING。
运行过程中的 leader 选举
当集群中 leader 服务器出现宕机或者不可用情况时,整个集群无法对外提供服务,进入新一轮的 leader 选举。
(1)变更状态。leader 挂后,其他非 Oberver服务器将自身服务器状态变更为LOOKING。
(2)每个 server 发出一个投票。在运行期间,每个服务器上 zxid 可能不同。
(3)处理投票。规则同启动过程。
(4)统计投票。与启动过程相同。
(5)改变服务器状态。与启动过程相同。
为了防止数据不一致,在选举期间服务不可用。