Zookeeper

Zookeeper是什么

ZooKeeper是一个分布式协调服务,可用于服务发现、分布式锁、分布式领导选举、配置管理等。ZooKeeper官方架构图如下:
在这里插入图片描述

这一切的基础,都是ZooKeeper提供了一个类似于Linux文件系统的树形结构(可认为是轻量级的内存文件系统,但只适合存少量信息,完全不适合存储大量文件或者大文件),同时提供了对于每个节点的监控与通知机制。
在这里插入图片描述

既然是一个文件系统,就不得不提ZooKeeper是如何保证数据的一致性的。后面将介绍ZooKeeper如何保证数据一致性,如何进行领导选举,以及数据监控/通知机制的语义保证。

ZooKeeper服务器角色

ZooKeeper集群是一个基于主从复制的高可用集群,每个服务器承担如下三种角色中的一种:

  • Leader: 一个ZooKeeper集群同一时间只会有一个实际工作的Leader,它会发起并维护与各Follwer及Observer间的心跳。所有的写操作必须要通过Leader完成再由Leader将写操作广播给其它服务器。

  • Follower: 一个ZooKeeper集群可能同时存在多个Follower,它会响应Leader的心跳。Follower可直接处理并返回客户端的读请求,同时会将写请求转发给Leader处理,并且负责在Leader处理写请求时对请求进行投票。

  • Observer: 角色与Follower类似,但是无投票权。 在这里插入图片描述

原子广播(ZAB)

为了保证写操作的一致性与可用性,ZooKeeper专门设计了一种名为原子广播(ZAB)的支持崩溃恢复的一致性协议。基于该协议,ZooKeeper实现了一种主从模式的系统架构来保持集群中各个副本之间的数据一致性。

根据ZAB协议,所有的写操作都必须通过Leader完成,Leader写入本地日志后再复制到所有的Follower节点。

一旦Leader节点无法工作,ZAB协议能够自动从Follower节点中重新选出一个合适的替代者,即新的Leader,该过程即为领导选举。该领导选举过程,是ZAB协议中最为重要和复杂的过程。

1、写Leader

在这里插入图片描述
由上图可见,通过Leader进行写操作,主要分为五步:

  1. 客户端向Leader发起写请求
  2. Leader将写请求以Proposal的形式发给所有Follower并等待ACK
  3. Follower收到Leader的Proposal后返回ACK
  4. Leader得到过半数的ACK(Leader对自己默认有一个ACK)后向所有的Follower和Observer发送Commmit
  5. Leader将处理结果返回给客户端

这里要注意:

  1. Leader并不需要得到Observer的ACK,即Observer无投票权
  2. Leader不需要得到所有Follower的ACK,只要收到过半的ACK即可,同时Leader本身对自己有一个ACK。上图中有4个Follower,只需其中两个返回ACK即可,因为(2+1) / (4+1) > 1/2
  3. Observer虽然无投票权,但仍须同步Leader的数据从而在处理读请求时可以返回尽可能新的数据
2、写Follower/Observer在这里插入图片描述

从上图可见:

  • Follower/Observer均可接受写请求,但不能直接处理,而需要将写请求转发给Leader处理
  • 除了多了一步请求转发,其它流程与直接写Leader无任何区别
3、读操作

Leader/Follower/Observer都可直接处理读请求,从本地内存中读取数据并返回给客户端即可。 在这里插入图片描述
由于处理读请求不需要服务器之间的交互,Follower/Observer越多,整体可处理的读请求量越大,也即读性能越好。

支持的领导选举算法

可通过electionAlg配置项设置ZooKeeper用于领导选举的算法。

到3.4.10版本为止,可选项有:

  • 0 基于UDP的LeaderElection
  • 1 基于UDP的FastLeaderElection
  • 2 基于UDP和认证的FastLeaderElection
  • 3 基于TCP的FastLeaderElection

在3.4.10版本中,默认值为3,也即基于TCP的FastLeaderElection。另外三种算法已经被弃用,并且有计划在之后的版本中将它们彻底删除而不再支持。

FastLeaderElection原理

1、myid

每个ZooKeeper服务器,都需要在数据文件夹下创建一个名为myid的文件,该文件包含整个ZooKeeper集群唯一的ID(整数)。例如,某ZooKeeper集群包含三台服务器,hostname分别为zoo1、zoo2和zoo3,其myid分别为1、2和3,则在配置文件中其ID与hostname必须一一对应,如下所示。在该配置文件中,server.后面的数据即为myid。

server.1=zoo1:2888:3888
server.2=zoo2:2888:3888
server.3=zoo3:2888:3888

格式如下:
server.serverid=serverhost:leader_listent_port:quorum_port

顾名思义,serverid是本服务器的id,leader_listen_port是该服务器一旦成为leader之后需要监听的端口,用于接收来自follower的请求,quorum_port是集群中的每一个服务器在最开始选举leader时监听的端口,用于服务器互相之间通信选举leader.

需要注意的是,server id并没有写在这个配置文件中,而是在datadir中的myid文件中指定,我理解这么做的目的是:所有的服务器统一使用一个配置文件,该配置文件里面没有任何与特定服务器相关的信息,这样便于发布服务的时候不会出错,而独立出来一个文件专门存放这个server id值.

2、zxid

类似于RDBMS中的事务ID,用于标识一次更新操作的Proposal ID。为了保证顺序性,该zkid必须单调递增。因此ZooKeeper使用一个64位的数来表示,高32位是Leader的epoch,从1开始,每次选出新的Leader,epoch加一。低32位为该epoch内的序号,每次epoch变化,都将低32位的序号重置。这样保证了zkid的全局递增性。

3、服务器状态
  • LOOKING: 不确定Leader状态。该状态下的服务器认为当前集群中没有Leader,会发起Leader选举。
  • FOLLOWING: 跟随者状态。表明当前服务器角色是Follower,并且它知道Leader是谁。
  • LEADING: 领导者状态。表明当前服务器角色是Leader,它会维护与Follower间的心跳。
  • OBSERVING: 观察者状态。表明当前服务器角色是Observer,与Folower唯一的不同在于不参与选举,也不参与集群写操作时的投票。
4、选票数据结构

每个服务器在进行领导选举时,会发送如下关键信息:

logicClock 每个服务器会维护一个自增的整数,名为logicClock,它表示这是该服务器发起的第多少轮投票

  • state 当前服务器的状态
  • self_id 当前服务器的myid
  • self_zxid 当前服务器上所保存的数据的最大zxid
  • vote_id 被推举的服务器的myid
  • vote_zxid 被推举的服务器上所保存的数据的最大zxid
5、投票流程
  1. 自增选举轮次
  2. 初始化选票
  3. 发送初始化选票
  4. 接收外部投票
  5. 判断选举轮次
  6. 选票PK
  7. 统计选票
  8. 更新服务器状态

具体图示看文末链接

ZooKeeper节点类型

ZooKeeper 提供了一个类似于 Linux 文件系统的树形结构。该树形结构中每个节点被称为 znode ,可按如下两个维度分类:

1、Persist vs. Ephemeral

  • Persist节点,一旦被创建,便不会意外丢失,即使服务器全部重启也依然存在。每个 Persist 节点即可包含数据,也可包含子节点

  • Ephemeral节点,在创建它的客户端与服务器间的 Session 结束时自动被删除。服务器重启会导致 Session 结束,因此 Ephemeral 类型的 znode 此时也会自动删除

2、Sequence vs. Non-sequence

  • Non-sequence节点,多个客户端同时创建同一 Non-sequence 节点时,只有一个可创建成功,其它匀失败。并且创建出的节点名称与创建时指定的节点名完全一样

  • Sequence节点,创建出的节点名在指定的名称之后带有10位10进制数的序号。多个客户端创建同一名称的节点时,都能创建成功,只是序号不同

ZooKeeper语义保证

ZooKeeper简单高效,同时提供如下语义保证,从而使得我们可以利用这些特性提供复杂的服务。

  • 顺序性: 客户端发起的更新会按发送顺序被应用到 ZooKeeper 上
  • 原子性: 更新操作要么成功要么失败,不会出现中间状态
  • 单一系统镜像: 一个客户端无论连接到哪一个服务器都能看到完全一样的系统镜像(即完全一样的树形结构)。注:根据上文《ZooKeeper架构及FastLeaderElection机制》介绍的 ZAB 协议,写操作并不保证更新被所有的 Follower 立即确认,因此通过部分 Follower 读取数据并不能保证读到最新的数据,而部分 Follwer 及 Leader 可读到最新数据。如果一定要保证单一系统镜像,可在读操作前使用 sync 方法。
  • 可靠性: 一个更新操作一旦被接受即不会意外丢失,除非被其它更新操作覆盖
  • 最终一致性: 写操作最终(而非立即)会对客户端可见

ZooKeeper Watch机制

所有对 ZooKeeper 的读操作,都可附带一个 Watch 。一旦相应的数据有变化,该 Watch 即被触发。

Watch 有如下特点:

  • 主动推送: Watch被触发时,由 ZooKeeper 服务器主动将更新推送给客户端,而不需要客户端轮询。
  • 一次性: 数据变化时,Watch 只会被触发一次。如果客户端想得到后续更新的通知,必须要在 Watch 被触发后重新注册一个 Watch。
  • 可见性: 如果一个客户端在读请求中附带 Watch,Watch 被触发的同时再次读取数据,客户端在得到 Watch 消息之前肯定不可能看到更新后的数据。换句话说,更新通知先于更新结果。
  • 顺序性: 如果多个更新触发了多个 Watch ,那 Watch 被触发的顺序与更新顺序一致。

利用watch机制和节点特性,可以实现分布式锁(公平用watch/非公平节点特性)和Leader选举(具体图示看文末链接)
此处说的Leader选举是指对依赖Zookeeper的分布式系统的选举而非Zookeeper本身的选举

ACL

Zookeeper采用ACL(AccessControlLists)策略来进行权限控制,类似于 UNIX 文件系统的权限控制。Zookeeper 定义了如下5种权限。

  1. create: 创建子节点的权限
  2. read: 获取节点数据和子节点列表的权限
  3. write: 更新节点的权限
  4. delete: 删除节点的权限
  5. admin: 设置节点ACL的权限

文章参考:点这里 ACL详细 会话管理 保证顺序一致性
其余参考:参考1 参考2 参考3

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值