解释 Apache ZooKeeper

415

我正在尝试理解ZooKeeper是如何工作和它的作用。是否有与ZooKeeper可比较的应用程序呢?

如果您了解的话,那么您会如何向外行人描述ZooKeeper?

我已经尝试过阅读Apache Wiki、ZooKeeper SourceForge等资料,但仍无法理解。

我刚刚阅读了http://zookeeper.sourceforge.net/index.sf.shtml,那么是否还有类似于它的其他服务呢?它是否只是复制服务器服务一样简单?


7
类似但不完全符合您所查找的答案:https://dev59.com/33M_5IYBdhLWcg3wNgKZ - zengr
3
http://www.cloudera.com/blog/2009/05/building-a-distributed-concurrent-queue-with-apache-zookeeper/ - zengr
你可以阅读这篇论文ZooKeeper: Wait-free coordination for Internet-scale systems,它是由两位雅虎工程师撰写的。 - yaphet
约58分钟的视频。 - Always Learning
请查看此文章:https://www.stackextend.com/zookeeper/centralized-configuration-with-apache-zookeeper/ - Mouad EL Fakir
显示剩余3条评论
8个回答

463
简而言之,ZooKeeper帮助您构建分布式应用程序。
它可以被描述为具有最终一致性的复制同步服务。它是强大的,因为持久化数据分布在多个节点之间(这组节点称为“集合”),一个客户端连接到其中任何一个(即特定的“服务器”),如果一个节点失败,则迁移;只要严格多数节点正常工作,ZooKeeper节点群就是活动的。特别地,主节点通过集合内的共识动态选择;如果主节点失败,则主节点角色将迁移到另一个节点。
写操作由主节点处理:这样就可以保证按顺序持久化写操作,即写操作是线性的。每次客户端向集合写入时,大多数节点会持久化信息:这些节点包括客户端的服务器以及显然的主节点。这意味着每次写操作都使服务器与主节点保持最新状态。然而,这也意味着您不能并发写入。
线性写入的保证是ZooKeeper不适合写密集型工作负载的原因。特别是不应将其用于交换大量数据(如媒体)。只要您的通信涉及共享数据,ZooKeeper都会帮助您。当数据可能被同时写入时,ZooKeeper实际上会妨碍您,因为它即使在写者的角度来看并不严格必要,也会强制执行操作序列。
这就是ZooKeeper的卓越之处:读取是并发的,因为它们由客户端连接到的特定服务器提供。但是,这也是最终一致性的原因:客户端的“视图”可能已过时,因为主节点以有限但未定义的延迟更新相应的服务器。
详细信息如下:

ZooKeeper的复制数据库由一棵znode树组成,它们大致表示文件系统节点(将它们视为目录)。每个znode可以通过一个字节数组进行增强,用于存储数据。此外,每个znode下面可能还有其他znodes,实际上形成了一个内部目录系统。

序列化znodes

有趣的是,znode的名称可以是序列化的,这意味着客户端在创建znode时提供的名称仅是前缀:完整的名称也由集合选择的顺序号给出。例如,如果多个客户端想要获取资源的锁,则可以在位置上同时创建序列化的znode,获得最低编号的客户端有权使用锁,从而实现同步目的。

临时znodes

此外,znode可以是临时的:这意味着只要创建它的客户端断开连接,它就会被销毁。这主要有助于了解客户端失败的情况,在客户端本身具有应该由新客户端承担的责任时,这可能是相关的。以锁为例,一旦持有锁的客户端断开连接,其他客户端就可以检查是否有资格使用锁。

监视器

与客户端断开连接相关的示例可能存在问题,如果我们需要定期轮询znode的状态。幸运的是,ZooKeeper提供了一个事件系统,可以在znode上设置监视器。这些监视器可以设置为在特定更改或删除znode或在其下创建新的子级时触发事件。这在与znode的序列化和临时选项结合使用时非常有用。

何时以及如何使用它

ZooKeeper的经典应用场景是分布式内存计算,在这种情况下,一些数据在客户端节点之间共享,并且必须以非常谨慎的方式进行访问/更新以实现同步。

ZooKeeper提供了构建同步原语的库,同时运行分布式服务器的能力避免了使用集中式(类似代理的)消息存储库时出现的单点故障问题。

ZooKeeper 是一个功能轻量级的系统,它没有提供领导者选举,锁定,屏障等机制,但可以在 ZooKeeper 原语之上编写这些机制。如果C/Java API对你来说太笨重,你应该依靠基于 ZooKeeper 构建的库,例如 cages 和尤其是 curator

阅读更多

除了官方文档外,我建议阅读《Hadoop权威指南》的第14章,该章节共有约35页,主要解释ZooKeeper所做的事情,并且提供一个配置服务的示例。


2
我不确定我理解你所建议的通信方案,但是你可以使用ZooKeeper从生产者“发布”信息,并让多个消费者读取它。另一方面,如果每种类型的服务器只存在一个实例,则使用ZK的好处很少。 - Luca Geretti
81
这段话的意思是,对于一个非专业人士来说,这并没有很好地解释ZooKeeper是什么。我何时需要ZooKeeper?我会向它写些什么?它解决了什么问题?它是一个键值存储器吗?一个搜索引擎?一个分布式锁?为什么我会选择ZooKeeper而不是Redis、文件、JIRA或便利贴等工具?你显然了解ZooKeeper的很多细节 - 但你能否用更通俗易懂的语言解释它呢? - Dan Passaro
1
由于Zookeeper具有线性写入,这是否意味着我不能使用异步API创建节点并在回调中获取响应?尽管在内部它可能不允许并发写入,但我是否遗漏了什么? - jdk2588
1
每当客户端向集合写入信息时,大多数节点都会持久化这些信息:这些节点包括客户端所连接的服务器和显然的主节点。您能否指向一个文档或其他解释此内容的资源?我想知道是否可能成功进行状态更改,但不包括客户端所连接的服务器(在这种情况下,客户端可能会经历无法读取自己写入的奇怪行为)。 - senseiwu
5
完全背道而驰,与所问的问题毫不相关。如果这是一枚时钟,他会寻找“计时装置”,而不是基于摆动周期、惯性矩和人造蓝宝石晶体的相互作用来描述主发条、齿轮传动和逃逸轮机构。 - Rick O'Shea
显示剩余2条评论

12

Zookeeper是最好的开源服务器和服务之一,有助于可靠地协调分布式进程。Zookeeper是一个CP系统(参考CAP定理),提供一致性和分区容错。跨所有节点复制Zookeeper状态使其成为最终一致性的分布式服务。

此外,任何新选举的领导者都将使用缺少的提案或状态快照更新其追随者,如果追随者缺少许多提案。

Zookeeper还提供了一个非常易于使用的API。如果您正在寻找示例,本博客文章“Zookeeper Java API示例”中有一些示例。

那么我们在哪里使用它?如果您的分布式服务需要集中、可靠和一致的配置管理、锁、队列等,您会发现Zookeeper是一个可靠的选择。


6
Zookeeper是一个CP系统(参考CAP理论),提供一致性和分区容错性。我认为Zookeeper有主节点和从节点,当主节点故障时,其中一个从节点将被选举为Leader,因此Zookeeper应该提供AP,但最终是一致的。 - YuFeng Shen
6
就 CAP 定理而言,“C” 实际上指的是可线性化。实际上,ZooKeeper 提供的是“顺序一致性”,这意味着来自客户端的更新将按照它们接收到的顺序应用。这比可线性化弱,但仍然非常强,比“最终一致性”强得多。ZooKeeper 不属于高可用性,原因在于如果无法选举出领导者(没有法定人数),那么 ZooKeeper 将失败请求。 - Binu George
你认为Apache Zookeeper可以作为外部系统用于执行共识吗?就像以下问题中所解释的那样:https://stackoverflow.com/q/70088996/5029509 - Questioner

10

它解决了什么问题?

假设我们有一个文件存储库,其中包含一百万个文件,并且每天每分钟都会增加文件数量。我们的任务是首先处理这些文件,然后将其删除。我们可以考虑的一种方法是编写一个脚本来执行此任务,并在多个服务器上并行运行多个实例。我们甚至可以根据需求增加或减少服务器数量。这基本上是分布式计算/数据处理应用程序。

在这里,我们如何确保同一文件不会同时被多个服务器选择和处理?为解决这个问题,所有服务器都应该共享关于当前正在处理哪个文件的信息。

这就是我们可以使用类似ZooKeeper的东西的地方。当第一个服务器想要读取一个文件时,它可以写入ZooKeeper,表示它将要处理的文件名。现在,其余的服务器可以查找ZooKeeper,并知道该文件已经被第一个服务器选中。

以下是一个简单的示例,需要在其中放置其他一些守卫才能正常运行,但我希望它能够说明Zookeeper的功能。
ZK基本上是一个数据存储,可以使用ZK API进行访问。但是不应该将其用作数据库。只应该存储少量的数据(通常为KB级别)。每个znode的上限是1MB。
ZK专门构建为分布式应用程序之间可以相互通信。 ZK的应用 “开箱即用”可用于:
- 存储配置:存储跨分布式应用程序访问的配置。 - 命名服务:在中心位置存储诸如服务名称和IP地址映射等信息,从而使用户和应用程序可以在网络上进行通信。 - 组成员资格:所有在分布式服务器上运行的应用程序都可以连接到ZK并发送心跳。如果任何一个服务器/应用程序停止工作,则ZK可以通知其他服务器/应用程序。
其他功能必须建立在ZooKeeper API之上。
  • 锁和队列 - 在分布式同步中非常有用。
  • 两阶段提交 - 在需要在多个服务器上提交/回滚时非常有用。
  • 领导者选举 - 您的分布式应用程序可以使用ZK进行领导者选举,以进行自动故障转移。
  • 共享计数器

下面是解释如何实现这些功能的页面https://zookeeper.apache.org/doc/current/recipes.html

ZooKeeper可以有更多的应用。根据您的分布式系统的要求,必须在ZK API之上构建这些功能。

注意:不应将ZK用于存储大量数据。它不是缓存/数据库。 请使用它交换分布式应用程序需要启动、运行和故障转移的小块信息。

数据是如何存储的?

数据存储在分层树形数据结构中。树中的每个节点称为 znode。znode 的最大大小为 1MB。znode 可以有数据和其他子 znode。将 znode 想象成计算机上的文件夹,该文件夹可以具有带有数据的文件,但是该文件夹本身也可以像文件一样具有数据。
为什么使用 ZK 而不是我们自己的自定义服务?
  • 原子性和持久性
  • Zookeeper本身是分布式和容错的。其架构涉及一个领导节点和多个从属节点。如果ZK从属节点宕机,它将自动故障转移。客户端会话被复制,因此ZK可以自动将客户端移动到另一个节点。如果领导节点宕机,则使用ZK共识算法选举新的领导者。
  • 由于数据存储在内存中,因此读取非常快。
  • 写入按照到达顺序写入。因此保持排序。
  • 监视器将向设置了对某些数据进行监视的客户端发送通知。这减少了轮询ZK的需要。请注意,监视器是一次性触发器,如果您收到监视事件并希望得到未来更改的通知,则必须设置另一个监视器。
  • 可用持久和临时znode。两者都存储在ZK磁盘上。这里的持久表示数据将在创建它的客户端断开连接后持久化。临时表示数据将在客户端断开连接时自动删除。不允许为临时znode设置子节点。
  • 还有持久顺序和临时顺序znode。这里的znode名称可以具有后缀序列号。类似于DB自动递增ID,这些序列号不断增加并由ZK管理。这对于实现队列、锁等非常有用。

有没有任何与Zookeeper相媲美的应用程序?

etcd - https://etcd.io/docs/v3.3/learning/why/#zookeeper


9
我对ZooKeeper有一定了解,但是"quorum"和"split brain"这两个术语让我有些困惑。也许我可以与您分享我的发现(我也认为自己是个外行人)。
假设我们有一个由5台服务器组成的ZooKeeper集群。其中一台服务器将成为领袖,其他服务器将成为追随者。
这5台服务器形成一个quorum。Quorum简单地意味着"这些服务器可以投票决定谁应该成为领袖"。
因此,投票是基于多数原则。多数原则只是指"超过半数",因此超过半数的服务器必须同意某个特定的服务器成为领袖。
因此可能会发生一件坏事情,叫做"split brain"。就我所理解的,split brain就是这样一个情况:5台服务器的集群分裂成两个部分,或者称之为"服务器团队",一个由2台服务器,另一个由3台服务器。这真的是一个糟糕的情况,因为如果两个"服务器团队"都必须执行特定命令,你怎么决定哪个团队应该优先?他们可能从客户端接收到不同的信息。因此,真的很重要知道哪个"服务器团队"仍然是相关的,哪个可以/应该被忽略。
多数原则也是您应该使用奇数台服务器的原因。如果您有4台服务器,并且发生了split brain情况,其中2台服务器分开,则两个"服务器团队"都可能会说"嘿,我们想决定谁成为领袖!"但是,你应该如何决定选择哪2台服务器?有5台服务器就很简单:有3台服务器的"服务器团队"具有多数票,可以选择新的领袖。
即使只有3台服务器中的1台失败,其他2台仍然构成多数,可以同意其中一台成为新领袖。
我意识到一旦你思考了一段时间并理解了这些术语,它们就不再那么复杂了。我希望这也能帮助任何人理解这些术语。

你认为Apache Zookeeper可以作为外部系统用于执行共识吗?就像以下问题中所解释的那样:https://stackoverflow.com/q/70088996/5029509 - Questioner

3

Zookeeper是一个集中式的开源服务器,用于维护和管理分布式集群环境中的配置信息、命名约定和同步。Zookeeper通过提供低延迟和高可用性,帮助分布式系统减少管理复杂性。Zookeeper最初是Hadoop项目的子项目,现在是Apache Software Foundation的顶级独立项目。

更多信息


4
为什么你认为 Zookeeper 是集中式的?Zookeeper 可以和应该运行在分布式环境中。 - Benjamin Hammer Nørgaard
您认为Apache Zookeeper能否用于作为外部系统执行共识,就像以下问题中所解释的那样?https://stackoverflow.com/q/70088996/5029509 - Questioner

2

2

我的方法来理解zookeeper,是通过CLI客户端进行试验。具体可以参考入门指南命令行界面

通过这种方式,我了解到zookeeper的外观与文件系统非常相似,客户端可以创建和删除对象,并读取或写入数据。

CLI命令示例

create /myfirstnode mydata
ls /
get /myfirstnode
delete /myfirstnode

自己试试

如何在Docker for Windows、Linux或Mac上在几分钟内启动一个Zookeeper环境:

一次性设置:

docker network create dn

在终端窗口中运行服务器:

docker run --network dn --name zook -d zookeeper
docker logs -f zookeeper

在第二个终端窗口中运行客户端:
docker run -it --rm --network dn zookeeper zkCli.sh -server zook

参见DockerHub上的镜像文档


你认为Apache Zookeeper可以作为外部系统用于执行共识吗?就像以下问题中所解释的那样:https://stackoverflow.com/q/70088996/5029509 - Questioner

0

Apache ZooKeeper 是一个用于协调和管理分布式应用程序配置的开源技术。它简化了维护配置细节、启用分布式同步以及管理命名注册表等任务。

它的名称非常贴切 - 想象一下动物管理员如何四处走动,照顾所有的动物,维护它们的围栏,喂养它们等等。

Apache ZooKeeper 可以与 Apache Pinot 或 Apache Flink 等 Apache 项目一起使用。Apache Kafka 也使用 ZooKeeper 来管理代理、主题和分区信息。由于 Apache ZooKeeper 是开源的,因此您可以将其与任何您选择的技术或项目配对,而不仅仅是 Apache Foundation 项目。


您认为Apache Zookeeper能否像下面的问题所解释的那样,作为外部系统用于执行共识呢?https://stackoverflow.com/q/70088996/5029509 - Questioner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接