“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

我建议你阅读《Hadoop中海量数据的分布式处理方法》系列中的讲座《Hadoop.ZooKeeper》的文字记录

什么是 ZooKeeper,它在 Hadoop 生态系统中的地位。 关于分布式计算的谎言。 标准分布式系统图。 协调分布式系统的困难。 典型的协调问题。 ZooKeeper 设计背后的原则。 ZooKeeper 数据模型。 znode 标志。 会议。 客户端API。 原语(配置、组成员身份、简单锁、领导者选举、无羊群效应的锁定)。 动物园管理员架构。 动物园管理员数据库。 扎布。 请求处理程序。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

今天我们来谈谈ZooKeeper。 这个东西非常有用。 与任何 Apache Hadoop 产品一样,它有一个徽标。 它描绘了一个男人。

在此之前,我们主要讨论了如何在那里处理数据,如何存储它,即如何以某种方式使用它并以某种方式使用它。 今天我想谈谈构建分布式应用程序。 ZooKeeper 就是可以让您简化此事的工具之一。 这是一种服务,旨在对分布式系统、分布式应用程序中的进程交互进行某种协调。

对此类应用程序的需求每天都在变得越来越多,这就是我们课程的目的。 一方面,MapReduce 和这个现成的框架允许您消除这种复杂性,并使程序员无需编写流程交互和协调等原语。 但另一方面,没有人保证无论如何都不必这样做。 MapReduce或其他现成的框架并不总是能完全取代一些无法使用它实现的情况。 包括MapReduce本身以及一堆其他Apache项目;它们实际上也是分布式应用程序。 为了使编写更容易,他们编写了 ZooKeeper。

与所有 Hadoop 相关应用程序一样,它是由 Yahoo! 开发的。 它现在也是一个官方的 Apache 应用程序。 它不像 HBase 那样积极开发。 如果你使用 JIRA HBase,那么每天都会有一堆错误报告、一堆优化建议,也就是说,项目的生命在不断地进行。 而ZooKeeper一方面是一个比较简单的产品,另一方面这也保证了它的可靠性。 而且它非常易于使用,这就是为什么它已成为 Hadoop 生态系统内应用程序的标准。 因此,我认为回顾它以了解它的工作原理以及如何使用它会很有用。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

这是我们某次讲座中的图片。 我们可以说它与我们迄今为止考虑的一切都是正交的。 这里指出的所有内容,在某种程度上,都可以与 ZooKeeper 配合使用,即,它是一项使用所有这些产品的服务。 HDFS 和 MapReduce 都没有编写自己专门为它们工作的类似服务。 因此,使用了ZooKeeper。 这简化了开发以及一些与错误相关的事情。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

这一切从何而来? 看起来我们在不同的计算机上并行启动了两个应用程序,用绳子或网格将它们连接起来,一切正常。 但问题是网络不可靠,如果您嗅探流量或查看低级别发生的情况,客户端如何在网络上交互,您经常会看到一些数据包丢失或重新发送。 TCP 协议的发明并非毫无意义,它允许您建立特定的会话并保证消息的传递。 但无论如何,即使是 TCP 也不能总是拯救你。 一切都有一个超时时间。 网络可能会暂时中断。 它可能只是眨眼。 这一切都导致您不能依赖网络的可靠性。 这是与编写在一台计算机或一台超级计算机上运行的并行应用程序的主要区别,在一台计算机或一台超级计算机上没有网络,但内存中有更可靠的数据交换总线。 这是一个根本的区别。

除此之外,在使用网络时,总是存在一定的延迟。 磁盘也有,但网络有更多。 延迟是一段延迟时间,可以很小,也可以非常大。

网络拓扑正在发生变化。 什么是拓扑——这是我们网络设备的布局。 有数据中心,有架子,还有蜡烛。 所有这些都可以重新连接、移动等。这一切也需要考虑在内。 IP 名称发生变化,流量传输的路由也会发生变化。 这也需要考虑在内。

网络在设备方面也可能发生变化。 从实践来看,我可以说我们的网络工程师非常喜欢定期更新蜡烛上的东西。 突然出了一个新的固件,他们对一些Hadoop集群并不是特别感兴趣。 他们有自己的工作。 对他们来说,最重要的是网络正常运行。 因此,他们想在那里重新上传一些东西,在他们的硬件上进行刷新,并且硬件也会定期更改。 所有这些都需要以某种方式考虑在内。 所有这些都会影响我们的分布式应用程序。

通常,由于某种原因开始处理大量数据的人认为互联网是无限的。 如果那里有一个几 TB 的文件,那么您可以将其带到您的服务器或计算机并使用 并观看。 另一个错误是在 Vim的 查看日志。 永远不要这样做,因为这很糟糕。 因为 Vim 尝试缓冲所有内容,将所有内容加载到内存中,尤其是当我们开始浏览此日志并查找某些内容时。 这些都是被遗忘的事情,但值得考虑。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

编写一个在一台具有一个处理器的计算机上运行的程序会更容易。

当我们的系统增长时,我们希望将其全部并行化,并且不仅在计算机上并行化,而且在集群上并行化。 那么问题来了:这件事如何协调? 我们的应用程序甚至可能不会相互交互,但我们在多台服务器上并行运行多个进程。 如何监控他们一切顺利? 例如,他们通过互联网发送一些东西。 他们必须在某处写入其状态,例如在某种数据库或日志中,然后聚合该日志并在某处对其进行分析。 另外,我们需要考虑到该进程正在运行并且正在运行,突然出现一些错误或崩溃,那么我们要多快才能发现它?

显然,这一切都可以被快速监控。 这也很好,但是监控是一个有限的东西,它可以让你在最高级别监控一些东西。

当我们希望我们的进程开始相互交互时,例如,向彼此发送一些数据,那么问题也就出现了——这将如何发生? 是否会出现某种竞争条件,它们是否会相互覆盖,数据是否会正确到达,沿途是否会丢失任何东西? 我们需要开发某种协议等。

所有这些过程的协调并不是一件小事。 它迫使开发人员下降到更低的水平,要么从头开始编写系统,要么不完全从头开始,但这并不是那么简单。

如果您想出了一种加密算法,甚至实现了它,请立即扔掉它,因为它很可能不适合您。 它很可能包含一堆您忘记提供的错误。 切勿将其用于任何严重的事情,因为它很可能不稳定。 因为所有现有的算法都经过了很长时间的时间检验。 它受到社区的干扰。 这是一个单独的主题。 这里也是一样。 如果您自己不可能实现某种进程同步,那么最好不要这样做,因为它非常复杂,并且会导致您走上不断寻找错误的不稳定道路。

今天我们谈论的是ZooKeeper。 一方面,它是一个框架,另一方面,它是一种服务,可以让开发人员的生活变得更轻松,并尽可能简化逻辑的实现和流程的协调。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

让我们记住标准的分布式系统可能是什么样子。 这就是我们谈论的——HDFS、HBase。 有一个Master进程来管理worker和slave进程。 他负责协调和分配任务、重启worker、启动新worker以及分配负载。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

更高级的是Coordination Service,即将协调任务本身移到一个单独的进程中,再加上并行运行某种backup或者standby Master,因为Master可能会失败。 如果Master倒下了,那么我们的系统就无法工作。 我们正在运行备份。 有些人指出主服务器需要复制以进行备份。 这也可以委托给协调服务。 但在这张图中,Master 本身负责协调 Worker;这里的服务正在协调数据复制活动。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

更高级的选择是所有协调都由我们的服务处理,就像通常所做的那样。 他负责确保一切顺利。 如果出现问题,我们会找出原因并尝试解决这种情况。 无论如何,我们留下了一个主站,他以某种方式与从站进行交互,并可以通过某些服务发送数据、信息、消息等。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

还有一种更高级的方案,当我们没有Master时,所有节点都是主从,行为不同。 但他们仍然需要相互交互,因此仍然需要一些服务来协调这些操作。 或许,按照这个原理工作的 Cassandra 就适合这个方案。

很难说这些方案中哪一个效果更好。 每个都有自己的优点和缺点。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

对于师父来说,没有必要害怕一些事情,因为,正如实践所表明的,他不太容易受到不断服务的影响。 这里最主要的是选择正确的解决方案来将该服务托管在一个单独的强大节点上,以便它拥有足够的资源,这样如果可能的话,用户就无法访问那里,这样他们就不会意外杀死这个进程。 但同时,在这样的方案中,从Master进程管理worker要容易得多,即从实现的角度来看,该方案更简单。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

这个方案(上图)可能更复杂,但更可靠。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

主要问题是部分失败。 例如,当我们通过网络发送消息时,发生某种意外,发送消息的人将不知道他的消息是否被接收以及接收方发生了什么,将不知道消息是否被正确处理,即他不会收到任何确认。

因此,我们必须处理这种情况。 最简单的事情就是重新发送此消息并等待我们收到响应。 在这种情况下,不考虑接收器的状态是否发生变化。 我们可能会发送一条消息并添加相同的数据两次。

ZooKeeper 提供了处理此类拒绝的方法,这也让我们的生活变得更轻松。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

正如前面提到的,这与编写多线程程序类似,但主要区别在于,在我们构建在不同机器上的分布式应用程序中,唯一的通信方式是网络。 本质上,这是一个无共享架构。 在一台机器上运行的每个进程或服务都有自己的内存、自己的磁盘、自己的处理器,并且不与任何人共享。

如果我们在一台计算机上编写多线程程序,那么我们可以使用共享内存来交换数据。 我们在那里有一个上下文切换,进程可以切换。 这会影响性能。 一方面是集群上的程序没有这个问题,但是网络有问题。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

因此,编写分布式系统时出现的主要问题是配置。 我们正在编写某种应用程序。 如果很简单,那么我们在代码中硬编码各种数字,但这很不方便,因为如果我们决定不希望超时半秒,而希望超时为一秒,那么我们需要重新编译应用程序并再次推出所有内容。 当它在一台机器上时,你可以重新启动它,这是一回事,但当我们有很多机器时,我们必须不断复制所有内容。 我们必须尝试使应用程序可配置。

这里我们讨论的是系统进程的静态配置。 这不完全是,也许从操作系统的角度来看,它可能是我们进程的静态配置,也就是说,这是一个不能简单地采取和更新的配置。

还有一个动态配置。 这些是我们想要动态更改的参数,以便在那里拾取它们。

这里有什么问题? 我们更新了配置,推出了它,那又怎样? 问题可能是,一方面我们推出了配置,但忘记了新事物,配置仍然存在。 其次,在我们推出时,配置在某些地方进行了更新,但在其他地方却没有更新。 我们的应用程序在一台计算机上运行的一些进程使用新配置重新启动,并在某处使用旧配置重新启动。 从配置的角度来看,这可能会导致我们的分布式应用程序不一致。 这个问题很常见。 对于动态配置,它更相关,因为它意味着它可以动态更改。

另一个问题是团体成员资格。 我们总是有一些工人,我们总是想知道他们中哪些人还活着,哪些人死了。 如果有Master,那么他必须了解哪些worker可以被重定向到客户端,以便他们运行计算或处理数据,哪些不能。 不断出现的一个问题是我们需要知道谁在我们的集群中工作。

另一个典型的问题是领导人选举,当我们想知道谁负责时。 一个例子是复制,当我们有一些进程接收写入操作,然后在其他进程之间复制它们时。 他将是领导者,其他人都会服从他,都会追随他。 有必要选择一个对每个人来说都明确的过程,这样就不会出现选择两个领导者的情况。

还存在互斥访问。 这里的问题更加复杂。 当您编写多线程程序并希望对某些资源(例如内存单元)的访问受到限制并仅由一个线程执行时,就会有互斥体这样的东西。 这里的资源可能是更抽象的东西。 来自我们网络不同节点的不同应用程序应该只接收对给定资源的独占访问权,而不是让每个人都可以更改它或在那里写入内容。 这些就是所谓的锁。

ZooKeeper 可以让您在一定程度上解决所有这些问题。 我将通过示例展示它如何让您做到这一点。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

不存在阻塞原语。 当我们开始使用某些东西时,这个原语将不会等待任何事件发生。 最有可能的是,这个东西将异步工作,从而允许进程在等待某些东西时不会挂起。 这是一个非常有用的东西。

所有客户端请求都按照通用队列的顺序进行处理。

在客户端看到更改的数据之前,客户端有机会收到有关某些状态更改、数据更改的通知。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

ZooKeeper 可以以两种模式工作。 第一个是独立的,在一个节点上。 这样方便测试。 它还可以在任意数量的服务器上以集群模式运行。 如果我们有一个包含 100 台机器的集群,那么它就没有必要在 100 台机器上运行。 选择几台可以运行 ZooKeeper 的机器就足够了。 它体现了高可用性的原则。 在每个正在运行的实例上,ZooKeeper 存储数据的完整副本。 稍后我会告诉你他是如何做到的。 它不会对数据进行分片或分区。 一方面,我们不能存储太多,这是一个缺点,另一方面,没有必要这样做。 这不是它的设计目的,它不是数据库。

数据可以缓存在客户端。 这是一个标准原则,这样我们就不会中断服务,也不会用相同的请求加载它。 聪明的客户端通常知道这一点并缓存它。

例如,这里发生了一些变化。 有某种应用程序。 选举了一位新的领导者,他负责处理写入操作等。 我们想要复制数据。 一种解决方案是将其放入循环中。 我们不断质疑我们的服务 - 有什么变化吗? 第二种选择更为优化。 这是一种监视机制,允许您通知客户端某些内容发生了变化。 就资源而言,这是一种更便宜的方法,并且对客户来说更方便。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

客户端是使用ZooKeeper的用户。

Server 是 ZooKeeper 进程本身。

Znode是ZooKeeper中的关键。 所有的znode都被ZooKeeper存储在内存中,并以层次图的形式组织起来,以树的形式。

有两种类型的操作。 第一个是更新/写入,当某些操作改变树的状态时。 这棵树很常见。

并且有可能客户端没有完成一次请求而断开连接,但可以建立一个会话,通过该会话与 ZooKeeper 进行交互。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

ZooKeeper 的数据模型类似于文件系统。 有一个标准根目录,然后我们就好像浏览从根目录开始的目录一样。 然后是第一级、第二级的目录。 这是所有 znode。

每个znode可以存储一些数据,通常不会很大,例如10KB。 每个 znode 可以有一定数量的子节点。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

Znode 有多种类型。 它们是可以被创建的。 并且在创建 znode 时,我们指定它应该属于的类型。

有两种类型。 第一个是临时旗帜。 Znode 存在于会话中。 例如,客户端已经建立了会话。 只要这个会话还存在,它就会存在。 为了不产生不必要的东西,这是必要的。 这也适用于我们在会话中存储数据原语非常重要的时刻。

第二种是顺序标志。 它在到达 znode 的途中增加计数器。 例如,我们有一个包含应用程序 1_5 的目录。 当我们创建第一个节点时,它接收到 p_1,第二个节点接收到 p_2。 而且当我们每次调用这个方法时,我们传递的是完整路径,仅表示路径的一部分,并且这个数字会自动递增,因为我们表示节点类型 - 顺序的。

常规 znode。 她将永远活着,并拥有我们告诉她的名字。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

另一个有用的东西是手表标志。 如果我们安装它,那么客户端就可以订阅特定节点的一些事件。 稍后我将通过一个示例向您展示这是如何完成的。 ZooKeeper 本身会通知客户端节点上的数据发生了变化。 但是,通知并不能保证某些新数据已到达。 他们只是说有些东西发生了变化,所以您仍然需要稍后通过单独的调用来比较数据。

正如我已经说过的,数据的顺序由千字节决定。 那里不需要存储大量文本数据,因为它不是数据库,而是动作协调服务器。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

我会告诉你一些关于会议的信息。 如果我们有多个服务器,那么我们可以使用会话标识符透明地在服务器之间移动。 相当方便。

每个会话都有某种超时。 会话是根据客户端在该会话期间是否向服务器发送任何内容来定义的。 如果他在超时期间没有传输任何内容,会话就会中断,或者客户端可以自行关闭它。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

它没有那么多功能,但您可以使用此 API 执行不同的操作。 我们看到 create 调用创建了一个 znode 并采用三个参数。 这是 znode 的路径,必须从根开始完整指定。 这也是我们想要传输到那里的一些数据。 以及标志的类型。 创建后,它返回 znode 的路径。

其次,你可以删除它。 这里的技巧是,第二个参数除了 znode 的路径之外,还可以指定版本。 因此,如果我们传输的 znode 版本与实际存在的版本相同,则该 znode 将被删除。

如果我们不想检查这个版本,那么我们只需传递“-1”参数即可。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

第三,它检查 znode 是否存在。 如果节点存在则返回 true,否则返回 false。

然后出现flag watch,可以让你监控这个节点。

即使在不存在的节点上,您也可以设置此标志,并在它出现时收到通知。 这也很有用。

还有一些挑战是 获取数据。 很明显我们可以通过znode接收数据。 您还可以使用旗帜手表。 在这种情况下,如果没有节点,则不会安装。 因此,你需要了解它的存在,然后接收数据。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

也有 设置数据。 这里我们传递版本。 而如果我们把这个传递下去,某个版本的znode上的数据就会被更新。

您还可以指定“-1”来排除此检查。

另一种有用的方法是 获取孩子。 我们还可以获得属于它的所有 znode 的列表。 我们可以通过设置标志监视来监控这一点。

及方法 同步 允许一次发送所有更改,从而确保它们被保存并且所有数据都已完全更改。

如果我们与常规编程进行类比,那么当您使用 write 等方法将某些内容写入磁盘时,在它返回响应给您之后,并不能保证您已将数据写入磁盘。 即使操作系统确信所有内容都已写入,磁盘本身也有一些机制,进程会经过多层缓冲区,只有在此之后,数据才会被放置在磁盘上。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

大多数情况下使用异步调用。 这允许客户端并行处理不同的请求。 您可以使用同步方法,但效率较低。

我们讨论的两个操作是更新/写入,这会更改数据。 它们是创建、设置数据、同步、删除。 而read是存在的,getData,getChildren。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

现在有一些示例说明如何制作在分布式系统中工作的原语。 例如,与某些东西的配置相关。 一名新工人出现了。 我们添加了机器并开始了这个过程。 还有以下三个问题。 它如何查询 ZooKeeper 的配置? 而如果我们想要改变配置,我们该如何改变呢? 那么我们改变之后,我们的那些工人怎么得到它呢?

ZooKeeper 使这相对容易。 例如,我们的 znode 树。 这里有一个用于我们的应用程序的节点,我们在其中创建一个附加节点,其中包含来自配置的数据。 这些可能是也可能不是单独的参数。 由于尺寸较小,配置尺寸通常也较小,因此很可能将其存储在这里。

您正在使用该方法 获取数据 从节点获取工作线程的配置。 设置为真。 如果由于某种原因该节点不存在,当它出现或更改时我们会收到通知。 如果我们想知道某些事情发生了变化,那么我们将其设置为 true。 如果该节点中的数据发生变化,我们就会知道。

设置数据。 我们设置数据,设置“-1”,即我们不检查版本,我们假设我们总是有一种配置,我们不需要存储很多配置。 如果您需要存储很多,则需要添加另一个级别。 这里我们认为只有一个,所以只更新最新的,所以不检查版本。 此时,所有先前订阅的客户端都会收到该节点发生变化的通知。 他们收到数据后,还必须再次请求数据。 通知是他们不接收数据本身,而仅接收更改通知。 此后他们必须要求新数据。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

使用原语的第二个选项是 团体会员。 我们有一个分布式应用程序,有一群工作人员,我们想了解他们都已就位。 因此,他们必须注册自己在我们的应用程序中工作。 我们还想从主进程或其他地方了解我们当前拥有的所有活跃工作线程。

我们如何做到这一点? 对于该应用程序,我们创建一个工作节点并使用 create 方法在其中添加一个子级别。 我的幻灯片有错误。 这里你需要 顺序 指定,那么所有的worker都会被一一创建。 请求有关该节点子节点的所有数据的应用程序接收所有存在的活动工作线程。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

对于如何在 Java 代码中完成此操作来说,这是一个非常糟糕的实现。 让我们从最后的 main 方法开始。 这是我们的类,让我们创建它的方法。 作为第一个参数,我们使用主机,我们连接的地方,即我们将其设置为参数。 第二个参数是组的名称。

连接是如何发生的? 这是所使用的 API 的一个简单示例。 这里一切都比较简单。 有一个标准类 ZooKeeper。 我们将主机传递给它。 并设置超时时间,例如5秒。 我们有一个名为connectedSignal 的成员。 本质上,我们沿着传输路径创建一个组。 尽管可以写入一些内容,但我们不会在那里写入数据。 而这里的节点是持久类型的。 本质上,这是一个一直存在的普通常规节点。 这是创建会话的地方。 这是客户端本身的实现。 我们的客户端将定期发送消息,表明会话处于活动状态。 当我们结束会话时,我们调用 close,就这样,会话就结束了。 这是为了防止我们出现问题,ZooKeeper 会发现并中断会话。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

如何锁定资源? 这里一切都有点复杂。 我们有一组工作人员,有一些我们想要锁定的资源。 为此,我们创建一个单独的节点,例如,名为 lock1。 如果我们能够创建它,那么我们就在这里获得了一把锁。 如果我们无法创建它,那么工作线程会尝试从这里获取 getData,并且由于节点已经创建,那么我们在这里放置一个观察者,一旦该节点的状态发生变化,我们就会知道它。 我们可以尝试有时间重新创建它。 如果我们获取了这个节点,获取了这个锁,那么当我们不再需要锁时,我们将放弃它,因为该节点只存在于会话中。 相应地,它将消失。 而另一个会话框架内的另一个客户端将能够锁定该节点,或者更确切地说,他将收到通知,表明某些内容已发生变化,并且他可以尝试及时执行此操作。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

如何选择主要领导者的另一个例子。 这个稍微复杂一点,但也比较简单。 这里发生了什么? 有一个主节点聚合所有工作人员。 我们正在尝试获取有关领导者的数据。 如果成功发生,即我们收到了一些数据,那么我们的工作人员就开始跟随这个领导者。 他相信已经有一个领导者了。

如果领导者由于某种原因死亡,例如摔倒,那么我们会尝试创建一个新的领导者。 如果我们成功了,那么我们的工人就会成为领导者。 如果此时有人设法创造了一位新的领导者,那么我们会尝试了解他是谁,然后追随他。

这里就出现了所谓的羊群效应,即羊群效应,因为当一个领导者去世时,最先出现的人就会成为领导者。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

在捕获资源时,您可以尝试使用稍微不同的方法,如下所示。 例如,我们想要获得一把锁,但没有赫特效应。 它包括这样一个事实:我们的应用程序请求一个已存在的带有锁的节点的所有节点 ID 的列表。 如果在此之前我们为其创建锁的节点是我们收到的集合中最小的,那么这意味着我们已经捕获了锁。 我们检查是否收到了锁。 作为检查,会有一个条件,即我们在创建新锁时收到的 id 是最小的。 如果我们收到了,我们就会进一步工作。

如果有某个 id 小于我们的锁,那么我们会在该事件上放置一个观察者并等待通知,直到发生变化。 也就是我们收到了这个锁。 而直到它脱落之前,我们不会成为最小的id,也不会收到最小的锁,这样我们就能够登录了。 如果不满足这个条件,那么我们立即去这里尝试再次获取这个锁,因为在这段时间里可能发生了一些变化。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

ZooKeeper 由什么组成? 主要有4件事。 这是处理过程——请求。 还有 ZooKeeper 原子广播。 有一个提交日志,其中记录了所有操作。 以及内存复制数据库本身,即存储整个树的数据库本身。

值得注意的是,所有的写操作都经过请求处理器。 读取操作直接进入内存数据库。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

数据库本身是完全复制的。 ZooKeeper 的所有实例都存储数据的完整副本。

为了在崩溃后恢复数据库,有一个提交日志。 标准做法是,在数据进入内存之前,将其写入内存,以便在崩溃时可以回放此日志并恢复系统状态。 并且还使用数据库的定期快照。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

ZooKeeper 原子广播是用于维护复制数据的东西。

ZAB 在内部从 ZooKeeper 节点的角度选择领导者。 其他节点成为她的追随者并期望她采取一些行动。 如果他们收到条目,他们会将它们全部转发给领导者。 他首先执行写入操作,然后向他的关注者发送有关更改内容的消息。 事实上,这必须是原子地执行的,即整个事情的记录和广播操作必须是原子地执行的,从而保证数据的一致性。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法” 它只处理写请求。 它的主要任务是将操作转换为事务性更新。 这是一个特别生成的请求。

而且这里值得注意的是,保证了同一操作的更新的幂等性。 这是什么? 这个东西如果执行两次,将具有相同的状态,即请求本身不会改变。 需要这样做,以便在发生崩溃的情况下,您可以重新启动操作,从而回滚此刻已经失效的更改。 在这种情况下,系统的状态将变得相同,即不应该出现一系列相同的情况,例如更新过程,导致系统的最终状态不同。

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

“哈普。 ZooKeeper”来自 Mail.Ru Group Technostream 系列“Hadoop 中大量数据的分布式处理方法”

来源: habr.com

添加评论