zookeeper

36 阅读8分钟

应用

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节点类型

  1. 持久节点:断开连接不会丢失
  2. 临时节点:断开连接丢失节点
  3. 持久顺序节点:有序的持久节点
  4. 临时顺序节点:有序的临时节点
  5. container节点(3.5.3新增)
  6. 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的过程

  1. 客户端向服务端注册watcher
  2. 服务端事件发生触发watcher
  3. 客户端回调watcher得到触发事件情况

注意:Zookeeper中的watch机制,必须客户端先去服务端注册监听,这样事件发送才会触

发监听,通知给客户端。

支持的事件类型:

None: 连接建立事件

NodeCreated: 节点创建

NodeDeleted: 节点删除

NodeDataChanged:节点数据变化

NodeChildrenChanged:子节点列表变化

DataWatchRemoved:节点监听被移除

ChildWatchRemoved:子节点监听被移除

特性说明
一次性触发watcher是一次性的,一旦被触发就会移除,再次使用时需要重新注册
客户端顺序回调watcher回调是顺序串行执行的,只有回调后客户端才能看到最新的数据状态。一个watcher回调逻辑不应该太多,以免影响别的watcher执行
轻量级WatchEvent是最小的通信单位,结构上只包含通知状态、事件类型和节点路径,并不会告诉数据节点变化前后的具体内容
时效性watcher只有在当前session彻底失效时才会无效,若在session有效期内快速重连成功,则watcher依然存在,仍可接收到通知;

应用场景

  1. 使用临时节点解决分布式锁
  2. 通过顺序节点生成分布式ID
  3. 注册中心
  4. 配置中心
  5. 集群管理

ZookeeperLeader选举原理

zookeeper的leader选举存在两个阶段,一个是服务器启动时leader选举,另一个是运行过程中leader服务器宕。

几个重要的参数:

  • 服务器 ID(myid):编号越大在选举算法中权重越大
  • 事务 ID(zxid):值越大说明数据越新,权重越大
  • 逻辑时钟(epoch-logicalclock):同一轮投票过程中的逻辑时钟值是相同的,每投完一次值会增加

选举状态:

  • LOOKING: 竞选状态
  • FOLLOWING: 随从状态,同步 leader 状态,参与投票
  • OBSERVING: 观察状态,同步 leader 状态,不参与投票
  • LEADING: 领导者状态

服务器启动时的 leader 选举

每个节点启动的时候都 LOOKING 观望状态,接下来就开始进行选举主流程。这里选取三台机器组成的集群为例。第一台服务器 server1启动时,无法进行 leader 选举,当第二台服务器 server2 启动时,两台机器可以相互通信,进入 leader 选举过程。

  1. 每台 server 发出一个投票,由于是初始情况,server1 和 server2 都将自己作为 leader 服务器进行投票,每次投票包含所推举的服务器myid、zxid、epoch,使用(myid,zxid)表示,此时 server1 投票为(1,0),server2 投票为(2,0),然后将各自投票发送给集群中其他机器。
  1. 接收来自各个服务器的投票。集群中的每个服务器收到投票后,首先判断该投票的有效性,如检查是否是本轮投票(epoch)、是否来自 LOOKING 状态的服务器。
  1. 分别处理投票。针对每一次投票,服务器都需要将其他服务器的投票和自己的投票进行对比,对比规则如下:
    • a. 优先比较 epoch
    • b. 检查 zxid,zxid 比较大的服务器优先作为 leader
    • c. 如果 zxid 相同,那么就比较 myid,myid 较大的服务器作为 leader 服务器
  1. 统计投票。每次投票后,服务器统计投票信息,判断是都有过半机器接收到相同的投票信息。server1、server2 都统计出集群中有两台机器接受了(2,0)的投票信息,此时已经选出了 server2 为 leader 节点。
  1. 改变服务器状态。一旦确定了 leader,每个服务器响应更新自己的状态,如果是 follower,那么就变更为 FOLLOWING,如果是 Leader,变更为LEADING。此时 server3继续启动,直接加入变更自己为 FOLLOWING。

运行过程中的 leader 选举

当集群中 leader 服务器出现宕机或者不可用情况时,整个集群无法对外提供服务,进入新一轮的 leader 选举。

(1)变更状态。leader 挂后,其他非 Oberver服务器将自身服务器状态变更为LOOKING。

(2)每个 server 发出一个投票。在运行期间,每个服务器上 zxid 可能不同。

(3)处理投票。规则同启动过程。

(4)统计投票。与启动过程相同。

(5)改变服务器状态。与启动过程相同。

为了防止数据不一致,在选举期间服务不可用。