注意:

在零停机时间内迁移 Kafka 和 Zookeeper 集群

简介

许多服务(云原生或内部部署)使用 Kafka 集群来满足异步消息传递需求,因为它是一种可扩展的消息传递技术。在某些情况下,您可能由于业务需求而不得不替换一组节点或整个集群。本教程介绍如何在不停机的情况下将 Kafka 和 Zookeeper 集群迁移到一组新节点。

问题陈述

为何将集群中的节点替换为另一个节点可能是一个挑战?在负载平衡器后面的节点集中添加或删除节点无处不在:添加新节点,耗尽要删除的现有节点,终止所有正在进行的连接后,将其关闭,将其从负载平衡器配置中删除等。

真正的挑战在于使用应用程序进行国家管理。通常,应用程序是无状态的,并将状态持久性委托给数据管理系统,例如关系数据库管理系统 (RDBMS)。与这些应用程序相反,Kafka 和 Zookeeper 在本地管理状态,即使用本地磁盘实现状态持久性。这意味着,如果不处理现有节点的本地状态,就不能简单地将节点替换为另一个节点。

此外,对于 Kafka,只需添加一个节点,就不会自动启动任何工作量重新平衡,即在代理之间重新分配主题分区。对于从现在开始创建的新主题,新节点仅参与工作量共享。

基于法定系统的操作问题(在本例中为 Zookeeper)是,它们需要预先知道群集大小,这意味着每个节点都需要了解群集中的所有其他节点。而且,为了进一步使事情复杂化,如果一次添加多个节点(具体数字取决于现有集群大小),则必须确保新添加的节点之一不会成为领导者,否则我们会丢失数据。

目标

先决条件

迁移 Kafka 集群

更换 Kafka 集群中的节点相对容易。添加新代理并调用主题分区迁移,一旦迁移完成,我们可以停用旧代理。Kafka 提供了用于执行分区迁移的 admin APIalterPartitionReassignments 可通过向主题添加其他分区副本,等待它们成为 ISR 的成员,然后交换分区引导器。

您必须禁用旧中介的新主题分区分配(如果应用程序逻辑在运行时创建主题),否则这将成为无休止的迁移循环。为了实现这一目标,可以使用主题创建 API 的变体,我们可以自己指定分区分配。下面列出了可遵循的示例算法。

簿记时可以遵循的迁移高级步骤(在迁移过程停止或失败时重新启动)。

  1. 断言已提供新代理 ID 映射并完成。

  2. 使用 AdminClient 检查是否有新代理可用。如果不是全部可用,则引发错误并终止。

  3. 使用 AdminClient 检查集群中是否存在主题 <kafka_topic_migration>

    • 如果主题 <kafka_topic_migration> 不存在,请通过在新代理上手动分配副本来创建该主题。此主题用于记账已重新分配的主题意味着已迁移。
  4. 使用使用者从头开始阅读主题 <kafka_topic_migration>。每条消息都是已重新分配给新代理的主题名称。

  5. 使用 AdminClient 列出集群中的所有可用主题。从此列表中,删除主题 <kafka_topic_migration>

  6. 从上述两个步骤中,找到要重新分配给新经纪人的主题。

  7. 对于每个主题:

    1. 创建映射 Map<TopicPartition,Optional<NewPartitionReassignment>> reassignment = new HashMap<>();

    2. 使用 AdminClient 描述查找其分区的主题。

    3. 对于每个分区:

      1. 通过将每个旧副本 ID(旧代理 ID)替换为相应的新代理 ID 来准备 NewPartitionReassignment 对象。如果代理 ID 映射不包含与副本 ID 对应的密钥,请记录警告并使用当前 ID(最有可能的原因是此主题已迁移并且我们未记账)。

      2. 将此条目添加到映射。

    4. 通过调用 alterPartitionReassignments 方法,使用 AdminClient 启动重新分配。

    5. 运行循环,通过列出重新分配 (listPartitionReassignments) 并检查其大小是否为零来检查此重新分配是否已完成。在每个循环之间休眠 N 秒。

    6. 验证每个分区的新副本是否与所需的副本匹配。

    7. 将此主题名称作为消息推送到 <kafka_topic_migration> 主题。

  8. 如果不再有要重新分配和终止的主题,请重复步骤 4 到 6。

迁移完成后,我们可以停用旧代理并禁用主题创建的自定义逻辑。

注:在停用旧代理之前,请确保此集群的所有客户机都已使用新代理更新了 bootstrap.servers 配置。

迁移 Zookeeper 集群

作为一个基于法定制度(提交任何操作,我们需要至少法定选票)和给定的领导者连任导致写入操作被停止,Zookeeper 迁移是最难的部分。有几种替换节点的方法。一种简单的方法是对整个群集执行多轮滚动重新启动,并在每轮中添加一个新节点。由于引导节点多次重新启动并在执行整体迁移时延迟,此方法可能不可接受。

注:由于在不同步所有数据(导致数据丢失)的情况下,新节点可能成为领导者,因此无法一次性添加所有新节点(作为参与者)。

切勿在与参与者相同的初始配置中指定多个联接服务器。目前,连接服务器不知道它们正在加入现有的合奏,如果多个联接器被列为参与者,它们可能会形成一个独立的法定数,从而产生一个分裂大脑的情况,例如独立于主合奏的处理操作。在初始配置中,可以将多个联接器列为观察者。

3.5.0 以上的 Zookeeper 版本中,我们支持动态重新配置 Zookeeper 集合。reconfigEnabled 标志应设置为 true,以便动态重新配置有效。有关更多信息,请参见 Dynamic Reconfiguration of the ZooKeeper Ensemble

可以使用角色 Observer 将新节点添加到集合中,并在上次提交的配置中对由服务器组成的联接器进行初始配置。例如,如果服务器 4 和 5 同时添加到 (1,2,3),则初始配置 4 将为 (1,2,3,4,5),其中 4 和 5 列为观察者。同样,5 的配置将是(1、2、3、4、5),其中 4 和 5 列为观察员。

注:以观察者身份列出联接者实际上并不会使它们成为观察者 - 这只会阻止它们意外地与其他联接者形成法定人数。相反,它们将联系当前配置中的服务器,并采用上次提交的配置(1、2、3),其中没有联接者。连接到当前领导者后,加入者将成为无表决权的追随者,直到系统重新配置并添加到集合中(根据需要作为参与者或观察者)。

所有节点都启动并运行后,将调用 reconfig API 以动态添加新节点作为参与者并从集合中删除旧节点。例如,使用 CLI。

reconfig -remove 1,2,3 -add
server.5=hostA:2111:2112;2113,6=hostB:2111:2112:participant;2113,7=
hostC:2111:2112:participant;2113*

在此步骤后,可以停用旧节点。

注:

确认

更多学习资源

浏览 docs.oracle.com/learn 上的其他实验室,或者通过 Oracle Learning YouTube 频道访问更多免费学习内容。此外,请访问 education.oracle.com/learning-explorer 以成为 Oracle Learning Explorer。

有关产品文档,请访问 Oracle 帮助中心