Advertisement

ZooKeeper相关知识点

阅读量:

ZooKeeper 介绍

ZooKeeper 由来

正式介绍 ZooKeeper 之前,我们先来看看 ZooKeeper 的由来,还挺有意思的。

以下是来自《从Paxos到ZooKeeper》第四章第一节的部分内容

ZooKeeper 的起源可以追溯至雅虎研究院的一个研究团队。在那个时期的研究人员观察到,在雅虎内部众多大型系统都依赖类似的机制来进行分布式协调。然而这些系统往往面临分布式单点问题。因此为了提高效率雅 href="https://zh.wikipedia.org/wiki/ZooKeeper" target="_blank">研究团队致力于构建一个无单点问题的一般性分布式协调框架

关于"ZooKeeper"这个项目的名称确实有一些有趣的背景故事。在项目的初期阶段, 因为之前内部许多项目都采用了以动物命名的方式(例如著名的Pig项目),雅虎的研发团队希望也能给这个新项目取一个具有idental意义的名字。当时, 该研究所的首席科学家RaghuRamakrishnan开玩笑地表示:"如果这样的话, 我们这里可能会逐渐变成动物园哦!"这句话一出, 各位同事纷纷表示同意, 建议把这个项目命名为"动物园管理员"—因为按照这个命名原则, 所有的以动物命名的分布式组件放在一起, 雅虎的研发中心看上去就像是一个大型动物园, 而ZooKeeper正是用来协调这种分布式环境的存在!因此,"ZooKeeper"这个名字就这样诞生了

ZooKeeper 概览

ZooKeeper 是一个开源项目,专注于实现一种高效的分布式协调机制,其核心理念在于将分散且易出错的一致性服务整合到统一的基础架构中,并通过丰富多样的API接口让用户能够方便地调用这些功能模块

原语: 操作系统或计算机网络中的术语体系。由一系列指令构成,并承担特定功能的任务流程。具有不可分割性特征,在执行过程中需保持连贯性

ZooKeeper 是一种高效可靠的技术方案,专为实现分布式系统中的数据一致性需求而设计.它广泛应用于构建如主题发布与订阅系统( topic-based pub/sub)、负载均衡机制以及名称服务器组件等.具体而言,这些功能均基于 ZooKeeper 的基础架构——即其提供的数据存储与事件监听两大核心组件.

ZooKeeper存储数据于内存中,并表现出色. 在读多于写的应用程序中特别表现出色, 因为'write'操作会导致所有服务器间的同步状态. ('read'超过'write'是协调服务的典型场景)

另外,很多顶级的开源项目都用到了 ZooKeeper,比如:

  • Kafka: zookeeper主要负责为kafka实现broker注册功能、topic管理以及多个partition的负载均衡。
    不过,在kafka版本更新至2.8后...引入基于raft协议的krat模式
    不再依赖zookeeper
    这大大简化了kafka的整体架构设计
  • hbase: zookeeper则负责对整个集群进行master节点管理
    并保存与提供regionserver的状态信息(包括是否在线)
  • hadoop: zookeeper则负责name node节点的高可用性保障

ZooKeeper 特点

  • 顺序一致性:所有事务请求将严格按照预定顺序被应用于 ZooKeeper 系统中。
    • 原子性:所有事务请求的处理结果在所有节点上呈现统一状态,即要么全部成功应用某项事务操作要么全部未成功应用。
    • 单一系统映像:无论客户端连接到哪个 ZooKeeper 服务器其服务端的数据模型都将保持一致。
    • 可靠性:一旦某个更改请求被成功应用其修改的结果会被永久存储直至下一次更改操作覆盖该结果。
    • 实时性:一旦数据发生变化其他节点会即时感知到变化并且每个客户端都能获得最新的系统视图。
    • 集群部署 :推荐使用奇数台(3~5 台)机器组成一个集群其中任意一台机器都需存储完整的数据副本且各节点间需实现通信同步功能从而保证客户端可连接至任意一台机器均能正常工作。
    • 高可用性:当某台机器发生故障时不会导致数据丢失只要集群中的故障率不超过一半即可保证系统的正常运行例如一个包含三台机器的集群最多只能容忍一台故障而五台机器组成的集群最多只能容忍两台故障而不影响整体系统的可用性

ZooKeeper 应用场景

在 ZooKeeper 概览中讨论了多种应用领域时提到了该系统常用于实现一系列功能包括数据发布与订阅机制负载均衡管理命名服务支持分布式协调与通知等功能以及帮助构建高效的分布式系统架构。其中详细介绍了如何通过 ZooKeeper 实现 Master选举过程以及相关的分布式锁与队列管理机制为分布式计算提供可靠的基础支持。

下面选 3 个典型的应用场景来专门说说:

  1. 名称服务系统:基于ZooKeeper协议定义的顺序节点能够自动生成全局唯一标识符。
  2. 数据发布订阅机制:通过该机制实现数据发布与订阅功能非常便捷。具体而言,在将数据发布至ZooKeeper监听节点后端时事监控中心可以根据实时变化自动更新配置信息。
  3. 分布式锁实现:通过创建唯一节点获得分布式锁权限,在完成相关操作后及时释放锁资源以避免死锁现象。此外,在实现过程中也需要运用Watcher机制来确保ZooKeeper服务的一致性。
    文章链接:分布式锁详解

具体来说,在ZooKeeper的作用下这些功能得以实现;然而ZooKeeper对于存储大量数据并不适合这一点值得注意

ZooKeeper 重要概念

Data model(数据模型)

ZooKeeper 的数据模型采用了分层的多路树形架构,在各个层级中各节点均支持存储不同类型的数据具体类型包括整数、字符串以及二进制序列此外,在 zookeeper 系统中所有 znode 都具有独特的路径标识符

ZooKeeper的主要功能是用来协调服务的,并非用于存储业务数据。因此建议应避免将较大的数据存储在znode中,并规定每个节点的数据规模限制为1MB。

通过下图更能清晰地看出:ZooKeeper节点的路径标识方式与Unix文件系统的路径表示非常类似;它们都采用斜杠符号‘/’作为分隔符来表示路径结构;开发人员不仅可以在该节点内插入数据内容;还可以在该节点下方创建子节点;这些基本操作将在后续章节中详细讲解。

znode(数据节点)

阐述了 ZooKeeper 树形数据模型之后,我们了解了每个数据节点在 ZooKeeper 中被称为 znode ,它是 ZooKeeper 中数据的基本构成单位。在实际操作中使用 ZooKeeper 时会频繁遇到这一概念,请将你需要存储的数据放置在其上。

我们通常是将 znode 分为 4 大类:

  • 持久(PERSISTENT)节点 :从不会消失,在Zookeeper集群发生故障后仍能持续存在直至被明确删除。
    • 临时(EPHEMERAL)节点 :其生命周期与客户端会话(session)紧密相关,在客户端会话终止时该临时节点也会随之消失,并且只能作为叶子结点存在而不能创建子节点。
    • 持久顺序(PERSISTENT_SEQUENTIAL)节点 :除了具备持久(PERSISTENT)特性之外,在子结点名称中也包含了次序信息。例如:/node1/app-1, /node1/app-2等。
    • 临时顺序(EPHEMERAL_SEQUENTIAL)节点 :除了具备临时(EPHEMERAL)特性之外,在子结点名称中也包含了次序信息

每个 znode 由 2 部分组成:

  • stat :状态信息
  • data :节点存放的数据的具体内容

如上文所示, 我将利用 get 命令获取 dubbo节点的相关信息.(get 命令在下文中将进行详细说明).

[zk: 127.0.0.1:2181(CONNECTED) 6] get /dubbo

该数据节点关联的数据内容为空

null

下面是该数据节点的一些状态信息,其实就是 Stat 对象的格式化输出

cZxid = 0x2
ctime = Tue Nov 27 11:05:34 CST 2018
mZxid = 0x2
mtime = Tue Nov 27 11:05:34 CST 2018
pZxid = 0x3
cversion = 1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 1

该类 Stat 存储着每个数据节点所具有的各项状态信息字段。其中包含了事务标识符 cZxid、生成时间 ctime 以及子节点数量 numChildren 等相关信息。

让我们深入了解每个 znode 状态信息所代表的具体内容如何?其中一部分内容源自《从 Paxos 到 ZooKeeper 分布式一致性原理与实践》一书(Guide 的理解仍有待进一步提升)。通过这种方式学习参考资料确实是一个不错的选择。

znode 状态信息 解释
cZxid create ZXID,即该数据节点被创建时的事务 id
ctime create time,即该节点的创建时间
mZxid modified ZXID,即该节点最终一次更新时的事务 id
mtime modified time,即该节点最后一次的更新时间
pZxid 该节点的子节点列表最后一次修改时的事务 id,只有子节点列表变更才会更新 pZxid,子节点内容变更不会更新
cversion 子节点版本号,当前节点的子节点每次变化时值增加 1
dataVersion 数据节点内容版本号,节点创建时为 0,每更新一次节点内容(不管内容有无变化)该版本号的值增加 1
aclVersion 节点的 ACL 版本号,表示该节点 ACL 信息变更次数
ephemeralOwner 创建该临时节点的会话的 sessionId;如果当前节点为持久节点,则 ephemeralOwner=0
dataLength 数据节点内容长度
numChildren 当前节点的子节点个数

版本(version)

在前面我们已经提到,在每一个 znode 对应的情况下(即对于每一个 znode),ZooKeeper 为每一个 znode 维护了一个名为 Stat 的数据结构。该数据结构 Stat 记录了该 znode 相关的三个版本:

  • dataVersion 指定为 current znode node 的 version number.
    • cversion 指定为 current znode child node 的 version.
    • aclVersion 指定为 current znode's access control list (ACL) 的 version.

ACL(权限控制)

ZooKeeper 基于 ACL(AccessControlLists)策略来实现对资源的权限管理,在机制上与 UNIX 系统中的文件权限管理机制相仿。

对于 znode 操作的权限,ZooKeeper 提供了以下 5 种:

  • CREATE : 具有生成子节点的能力
  • READ :能够读取节点信息并列举其所有子节点。
  • WRITE : 能够对节点信息进行修改或更新。
  • DELETE : 具备删除子节点的功能。
  • ADMIN : 拥有管理访问控制列表(ACL)的能力。

在操作中需要特别注意的是,在创建(CREATE)和删除(DELETE)这两种操作中都涉及到子节点的访问权限控制。

对于身份认证,提供了以下几种方式:

  • system name is the default mode, allowing all users to access without any restrictions.
    • authentication functionality defaults to not using an ID, representing authenticated users at all times.
    • digitation authentication mechanism employs username and password for identity verification.
    • Ip address filtering mechanism is implemented to restrict or block specified IP addresses.

Watcher(事件监听器)

Watchers(事件监听器),是 ZooKeeper 中的一个核心功能特性。ZooKeeper允许用户在指定节点上注册一些watchers,并且在某些特定触发事件发生时,ZooKeeper 服务端会将事件发送至感兴趣的目标客户端,ZooKeeper 这一机制正是其实现分布式协同服务的重要基础。

会话(Session)

Session 可以被视为 ZooKeeper 服务器与客户端之间的一个 TCP 长连接。通过这一连接,客户端能够利用心跳机制维持有效的通信会话,同时也能够向 ZooKeeper 服务器发送请求并接收响应,同时还能通过该连接接收来自服务器的 Watcher 事件通知。

Session具有名为sessionTimeout的一个属性,在该属性所定义的时间范围内表示该会话的有效截止时间点。当发生服务器过载、网络中断或客户端主动终止连接等情况时,在上述时间段内重新连接至集群中的任一节点即可维持原有对话关系。

在创建客户端会话之前,在该系统中将按客户端进行分配并为每个客户端自动赋予一个 sessionid;其中 zookeeper 会话采用该 sessionid 作为其关键参数,并确保所有服务器生成的 sessionid 均为唯一标识以避免冲突。

ZooKeeper 集群

为了确保系统的高可用性,在部署ZooKeeper时采用集群模式是最优选择。这种集群模式能够容忍部分服务器故障而不影响系统整体运行。一般情况下,只需要配置3台服务器即可组成一个有效的ZooKeeper集群。ZooKeeper官方提供的架构图就是一个典型的ZooKeeper集群对外服务的例子。

ZooKeeper 集群架构

上图中每一个节点代表一个安装ZooKeeper服务的计算机。构成ZooKeeper服务的所有节点都会在内存中管理当前的整体状态,并与各台服务器保持持续通信联系。整个集群系统通过ZAB协议(ZooKeeper Atomic Broadcast)实现数据一致性机制。

典型集群模式:Master/Slave 模式(主备模式) 。在该模式下,默认情况下采用 master 节点作为主要节点负责事务提交功能并处理 write 操作;其他 slave 节点则通过异步复制机制从 master 节点同步最新的数据来执行 read 操作。

ZooKeeper 集群角色

然而,在 ZooKeeper 中未采用传统的 Master/Slave 模型,而是采用了 Leader、Follower 和 Observer 三种角色作为核心组件。如图所示

ZooKeeper 节点群中所有节点通过一种称为 Leader 选举机制 的方式共同选出一台独特的 Leader 节点。该 Leader 不仅具备处理 write 操作的能力,同时也支持 read 操作。除了 Leader 节点外的所有其他节点——即 从属节点(Follower)观察节点(Observer)——都仅负责 read 操作。然而,在功能上二者存在显著差异:观察节点不参与 Leader 的选举过程,并且也不参与 write 操作中的‘过半 write 成功’策略这一关键步骤。因此,在不牺牲 writes 性能的前提下, observer 节点能够显著提升集群整体的 read 性能。

角色 说明
Leader 为客户端提供读和写的服务,负责投票的发起和决议,更新系统状态。
Follower 为客户端提供读服务,如果是写服务则转发给 Leader。参与选举过程中的投票。
Observer 为客户端提供读服务,如果是写服务则转发给 Leader。不参与选举过程中的投票,也不参与“过半写成功”策略。在不影响写性能的情况下提升集群的读性能。此角色于 ZooKeeper3.3 系列新增的角色。

ZooKeeper 集群 Leader 选举过程

在Leader节点发生网络中断、崩溃退出或重启等异常情况时,该选举过程会被启动,并从而选出新的Leader节点。

这个过程大致是这样的:

  1. Leader election(选举阶段):参与者在初始均进入选举阶段,在获得超过半数参与者的投票后即可成为准领导者。
  2. Discovery(发现阶段):参与者将与准领导者同步事务提议,并在此过程中保持最新的事务提议信息。
  3. Synchronization(同步阶段):基于leader所掌握的最新提议历史信息,集群中的所有副本将执行相应的操作。
  4. Broadcast(广播阶段):当leader完成所有操作后对外提供服务并进行消息广播;当新节点加入时,则会对其执行同样的操作以保持一致性。

ZooKeeper 集群中的服务器状态有下面几种:

  • Looking into the process to identify potential issues.
    • The leadership state is characterized by nodes designated as Leaders.
    • The following state involves nodes designated as Followers.
    • The observing state includes nodes designated as Observers, which do not participate in the selection of Leaders.

ZooKeeper 集群为啥最好奇数台?

当zookeeper节点发生故障后剩余节点数量超过故障节点数量时,整个zookeeper系统才依然可用。假设集群中有n台zookeeper服务节点,则剩余服务节点数必须超过n/2。总结一下,无论是采用2n还是2n-1的容错机制,其容忍度均为n-1,我们可以先自行思考一下这个问题,这其实是一个基础性的问题。

当给定n=3台ZooKeeper服务器时,在发生故障时最多只能有1台不可用;而当有n=4台时,则最多也只能出现1台故障。
当我们面临n=5台的情况时,在发生故障时最多只能有2台不可用;而对于n=6的情况,则同样地最多也只能出现2台故障。

综上,何必增加那一个不必要的 ZooKeeper 呢?

ZooKeeper 选举的过半机制防止脑裂

何为集群脑裂?

对于一个集群系统而言,在实际部署中常见做法是将多台服务器分部署于不同的机房中以增强其整体的可用性。为了确保系统的可靠性,在保证可用性的前提下可能会遇到机间网络线路出现故障的情况这会导致整个机房内的网络连接中断从而使得原本连通的整体被分割成若干个独立的小集群系统针对这种情况各个子集群会自主选举出一个作为管理核心以实现系统的稳定运行这一过程有时会被形象地称为'脑裂'现象

具体来说,在一个由6台服务器组成的分布式集群中(整体结构包括两个互连的子集群),每个子集群包含3台服务器运行在同一物理机架上。通常情况下只有一个主节点(Leader)负责协调服务分配。然而,在两个子集群之间的网络出现中断时(即子集群之间无法通信),每个子集群内的所有服务器都会误判对方子集群的所有服务器已处于不可用状态,并自主选举本子集群内的主节点对外提供服务操作。如果系统缺少过半数主节点支持,则会在网络恢复后立即发现存在两个主节点(即出现了类似于大脑出现分裂的现象)。在这种脑裂状态中(即存在两个独立的主节点同时提供服务),可能会导致数据一致性问题的出现

过半机制是如何防止脑裂现象产生的?

ZooKeeper's majority-based mechanism prevents the occurrence of two leaders. This is because a quorum of no more than half the nodes cannot elect a leader, which ensures that regardless of how the machine resources are allocated, a failure scenario involving partitioning (brain split) cannot occur.

ZAB 协议和 Paxos 算法

从核心机制上来说,可以说 Paxos 算法构成了 ZooKeeper 的基础架构。然而, zookeeper 未完全沿用 Paxos 而是采用了 ZAB 作为其核心一致性机制.此外,在 zookeeper 官方文档明确说明, zab 协议并非如 Paxos 那般 具备通用性,它是一个专为 zookeeper 设计的一种崩溃后可恢复的原子消息广播协议.

ZAB 协议介绍

该协议专为分布式系统 zookeeper 提供了一种在节点崩溃时可恢复的原子广播机制。 zab 协议作为 zookeeper 的核心组件,在其中发挥着维护数据一致性的关键作用。 通过采用主从复制机制和选举日志的方式,在节点故障时能快速切换到可用节点以维持集群内数据的一致性。

ZAB 协议两种基本的模式:崩溃恢复和消息广播

ZAB 协议包括两种基本的模式,分别是

  • 崩溃恢复 :当服务框架启动时或是Leader出现故障等情况,ZAB协议会启动修复机制并选出新的Leader.一旦集群中有超过一半的Follower完成与Leader的数据同步,ZAB就会停止修复过程.其中,数据同步即数据复制,确保超过一半节点与Leader的数据状态一致.
  • 消息广播 :一旦集群中有超过一半的Follower完成与Leader的数据同步,服务框架即可进入消息分发模式.新加入的Node若遵守ZAB协议, upon joining will automatically enter data recovery mode: locate Leader and synchronize data, then participate in broadcast process.

ZooKeeper VS ETCD

ETCD 主要作为一种 强一致性的分布式键值存储, 它提供了一种可靠的方式用于存储需要由分布式系统或机器集群访问的数据. ETCD 其内部采用了 raft 算法作为一致性算法, 基于 go 语言实现.

类似于 ZooKeeper 的 ETCD,在数据发布/订阅场景中同样展现出良好的性能特点;在负载均衡场景中可提供更为均匀的任务分配能力;同时在分布式系统中的命名服务实现上也表现出色;此外,在分布式协调与通知机制以及分布式锁实现方面均具备显著优势;那么该如何选择两者之间的区别呢?

这篇文章给出了如下的对比表格(我进一步做了优化),可以作为参考:

ZooKeeper ETCD
语言 Java Go
协议 TCP Grpc
接口调用 必须要使用自己的 client 进行调用 可通过 HTTP 传输,即可通过 CURL 等命令实现调用
一致性算法 Zab 协议 Raft 算法
Watcher 机制 较局限,一次性触发器 一次 Watch 可以监听所有的事件
数据模型 基于目录的层次模式 参考了 zk 的数据模型,是个扁平的 kv 模型
存储 kv 存储,使用的是 ConcurrentHashMap,内存存储,一般不建议存储较多数据 kv 存储,使用 bbolt 存储引擎,可以处理几个 GB 的数据。
MVCC 不支持 支持,通过两个 B+ Tree 进行版本控制
全局 Session 存在缺陷 实现更灵活,避免了安全性问题
权限校验 ACL RBAC
事务能力 提供了简易的事务能力 只提供了版本号的检查能力
部署维护 复杂 简单

在存储能力、全局会话以及监视器机制等方面存在一定的局限性,ZooKeeper 的表现已无法满足现代分布式系统的需求. 随着开源社区的发展,越来越多的项目正在转向采用 Raft 技术或其他分布式协调服务来替代 Zookeeper,例如: Kafka不需要ZooKEEPER:移除依赖,以及 避免使用ZOOKEEPER.

在功能覆盖范围上与 zookeeper 接近甚至超越,并实现了 zookeeper 的替代方案

总结

  1. ZooKeeper 实际上是一个分布式系统(只要多数节点存活,ZooKeeper 就能正常运行)。
  2. 为了确保高可用性, 建议采用集群部署模式,ZooKeeper 可能在集群大部分成员在线的情况下仍能正常工作(即能够容忍一定数量的故障)。
  3. zookeeper 将数据存储在内存中,从而实现了高吞吐量和低延迟的特点(然而内存限制了其存储容量,这一限制也是降低 zookeeper 内存使用规模的重要原因之一)。
  4. zookeeper 是高性能系统,在"读"超"写"的应用场景下尤为突出(因为"写"操作会导致所有服务器同步状态更新)。
  5. zookeeper 具有临时节点概念:当客户端会话持续活跃时,临时节点将一直存在;而一旦会话结束,临时节点就会被删除;持久节点则指的是从创建后未被删除的状态直到手动清除为止的状态(除非主动进行移除操作)。
  6. zookeeper 核心功能主要包括:① 负责管理用户提交数据的接收与存储;② 提供对数据节点监听的功能以支持应用逻辑需求)。

全部评论 (0)

还没有任何评论哟~