技术干货|AutoMQ:在 Kafka 中无需使用 Cruise Control 实现自动分区重分配

AutoMQ 的无状态 Broker 与自我平衡特性

文章导读

AutoMQ 是基于云原生重新设计的新一代 Kafka,并且已在 GitHub 开源。它完全兼容 Apache Kafka,通过将存储分离至 S3,可降低 90% 的成本,并能实现秒级弹性扩展,为用户提供低成本、高性能和无限容量的流存储服务。

自从 AutoMQ 正式开源以来,凭借其创新的架构设计和对 Kafka 协议的高度兼容,在海内外开发者社区迅速获得关注。截至目前,GitHub Star 数已接近 6.8k,成为近年来开源流处理基础设施领域的热门项目之一。

今天我们分享的内容,是来自海外开发者的另外一篇深度技术解读文章的翻译。他结合 AutoMQ 自研架构,重点介绍了如何在无需依赖 Cruise Control 的前提下,实现 Kafka 分区的自动重分配机制。文章内容详实,逻辑清晰,并配有架构图示,对于理解 Kafka 再平衡机制和 AutoMQ 的技术优势具有很高的参考价值。

希望本文能为对 Kafka 弹性方案、集群运维自动化感兴趣的读者,提供新的思路与启发。欢迎转发与交流。

注意:内容原始内容为英文,如需追求最原汁原味和准确的阅读体验,请直接点击底部 [查看原文] 阅读原始英文素材。

简介

如果你曾在公司中管理过 Kafka 部署,那么很可能处理过跨集群的 Partition 重组工作。由于 Kafka 的计算与存储紧密耦合,当集群成员发生变化(例如添加或移除 Broker)或用户希望在 Broker 之间进行负载均衡时,必须重新分配 Partition replicas ,从而引发大规模数据迁移。

Kafka 提供了用于处理重分配的脚本,但该过程依赖用户手动操作,且在规划层面缺乏稳健性。像 AutoMQ2024 这样的工具应运而生,能够基于集群状态实现副本的自动平衡,并制定更为复杂的重分配方案。然而,数据迁移的问题依然存在。本周我们将探讨 AutoMQ 如何应对 Kafka 的重平衡挑战。

AutoMQ 是一款云原生解决方案,提供 100% 的 Kafka 协议兼容性,并将数据完全存储在 Object Storage 上。这种架构在保障低延迟与高吞吐性能的同时,实现了高性价比的 Kafka 替代方案。更重要的是,你再也无需在 Broker 之间传输数据。

Kakfa Partitions

让我们先回顾一下 Kafka 的术语。

Kafka 的数据单位是 Message ,Kafka 中的消息被组织在 Topic 中,你可以将 Message 类比为数据库系统中的" Row ",而主题就像" Table ",一个 Topic 会被划分为多个 Partition 。

每个 Partition 对应一份 Logical Log 。从物理上看,这 Log 由若干个大小大致相同的 Segment File 组成,假设每个段为 1GB。当一条 Message 写入 Partition 时,Broker 会将其追加到最后一个 Segment File 中。

为了确保数据在系统中的持久保存和高可用性,Kafka 会将每个 Partition 的数据复制到多个 Broker 上,复制的数量由配置中的 Replica Factor 决定。

这种副本机制可以在某个 Broker 发生故障时自动切换到其他副本节点,从而保证 Message 不会因节点宕机而丢失或不可用。每个 Partition 通常有一个负责读写的 Leader ,以及零个或多个用于备份的 Follower 。所有写入请求必须发送到 Leader,而读取请求可以由 Leader 或对应的 Follower 处理。

为了避免高流量 Topic 的所有 Partition 被集中分配到少数节点,Kafka 会采用轮询( Round-Robin )策略,将各个 Partition 的副本均匀分布到整个集群中,从而实现负载均衡并提升系统整体的稳定性和吞吐能力。

Kafka中的副本重新

分配

当 Kafka 集群中的副本被分布在不同 Broker 上时,如果某个现有 Broker 宕机,或者新增了一个 Broker,会发生什么?这时候就需要对 Kafka 的副本进行重分配。

设想一个场景:我们有三个 Broker,以及两个 Partition,每个 Partition 拥有两个副本:

ꔷ 当某个 Broker 故障时,Kafka 会自动将原本由该 Broker 作为 Leader 的 Bartition 的领导权重新分配给其他持有该副本的 Broker。此外,为了维持原有的 Replica Factor,Kafka 可能还会在其他可用 Broker 上创建新的副本来补足。

ꔷ 当有新的 Broker 加入集群时,Kafka 会重新分配副本,以保证不同 Broker 之间的负载更加均衡。

除了集群成员变更这种情况外,为了实现 Broker 间的负载均衡,Kafka 也会需要进行 Partition 副本的重分配。合理分布数据可以防止"热点问题",即某些 Partition 接收的流量明显高于其他 Partition。同时,数据在 Broker 间的均匀分布有助于资源的最优利用。

Kafka 的开源版本支持一个用于辅助 Partition 重新分配的工具,称为 Kafka-reassign-partitions(Bin/kafka-reassign-partitions.sh)。该工具支持三种模式运行:

ꔷ **-generate:**此模式用于创建 Partition 重分配计划;用户提供一组 Topic 和一组 Broker 后,工具会生成一个候选重分配计划,将这些 Topic 的 Partition 移动到新的 Broker 上。

ꔷ **-execute::**此模式下,工具根据用户提供的重分配计划执行操作。该计划可以是用户手动创建的自定义计划,也可以通过 --generate 选项生成。

ꔷ **-verify:**工具会验证上一次 --execute 操作中所有列出的 Partition 的重分配状态。

然而,该重分配过程通常需要用户手动完成,容易出错且效率低下。那么,有没有办法自动完成重分配操作呢?幸运的是,已有第三方工具专为此目的而开发。

Linkedln 的 Cruise Control

Cruise Control 是一款用于大规模运行 Apache Kafka 集群的工具。随着 Kafka 在企业中的广泛应用,越来越多公司面临管理大型 Kafka 集群的挑战。在 LinkedIn,Kafka 集群规模达到了约 7000 个以上的 Broker,因此如何对 Kafka 的工作负载进行平衡成为一项非常复杂的任务。此外,大规模 Kafka 集群的监控与问题检测也同样至关重要。

Cruise Control 提供了如下核心功能:

ꔷ 资源利用率追踪。

ꔷ Kafka 集群当前状态的可观测性。

ꔷ Kafka 集群的异常检测、警报,以及自愈功能。

ꔷ 添加和删除 broker、集群重平衡等管理操作。

ꔷ 生成具有多种目标的重新分配计划。

Cruise Control 依赖最近的副本负载信息对集群进行优化。它会定期收集 Broker 和 Partition 两个层级上的资源使用数据,以获取各 Partition 的流量模式。基于这些流量模式,Cruise Control 可以评估每个 Partition 对 Broker 的负载影响,并据此构建集群的工作负载模型,从而模拟 Kafka 集群的运行状态。

其优化器(Goal Optimizer)会基于用户设定的一系列优化目标(Goals)探索多种优化方案,生成最合适的负载重分配建议。

这种方案与-Kafka-reassign-partitions 有本质区别:Kafka 原生工具仅基于用户输入的参数执行再平衡,而 Cruise Control 通过构建工作负载模型,能为再平衡计划提供更完善的目标策略集。

尽管 Cruise Control 能够有效降低再平衡操作的开销,但它仍无法避免跨 Broker 迁移数据所带来的网络传输开销。在数据在 Broker 之间迁移期间,Kafka 集群需要一定时间来达到新的负载平衡状态。

这也意味着,使用 Cruise Control 或其他第三方工具进行负载均衡时,实际执行过程可能存在一定程度的不准确性:工具在执行优化决策时,是基于当时的集群快照进行操作的。而由于 Kafka 的数据需要进行副本同步,执行过程本身会比较缓慢。等到决策真正被执行时,集群的状态可能已经发生了较大变化,从而导致原有决策失效或效果下降。

这种问题在 Kafka 中始终存在,根本原因在于其设计理念:强调存储与计算的紧密耦合,这虽然带来了性能上的优势,但也限制了集群在负载动态调整方面的灵活性。

AutoMQ :无需数据迁移

AutoMQ 的设计让一切变得简单。AutoMQ 在完全兼容 Apache Kafka 协议(100% Kafka protocol)的基础上,引入了共享存储架构,用以替代 Kafka 中 broker 的本地磁盘,其设计目标是实现完全无状态(Stateless)的系统架构。

传统 Kafka Broker 会将 Message 直接写入操作系统的页缓存(OS Page Cache),而 AutoMQ Broker 首先将 Message 写入堆外内存缓存(Off-heap Memory Cache),进行批量聚合后再写入对象存储(如 S3)。为了保障在写入对象存储前出现故障时的数据持久性,AutoMQ 引入了可插拔的预写日志(WAL,Write-Ahead Log)机制。Broker 在返回消息写入成功的确认(Ack)前,必须先将消息写入 WAL 中,然后再异步写入对象存储。如果 Broker 故障,AutoMQ 会利用 WAL 中的数据进行恢复。

通过这种方式,AutoMQ 实现了计算与存储的完全分离(Compute-storage Separation)。这一架构设计意味着两个关键事实:

ꔷ 对象存储自身提供了数据的持久性与高可用性,因此无需在多个 Broker 之间复制数据。每个 Partition 只需保留一个副本,即 Leader。

ꔷ Broker 完全无状态,它与 Partition 之间的关联仅通过 Metadata 维护,而非实际在本地磁盘上存储数据。

因此,AutoMQ 的负载重分配过程变得极为简单:无需迁移任何数据,只需调整 Broker 与 Partition 之间的元数据映射关系。这使得决策能够快速、准确且高效地执行。

说到元数据,AutoMQ 使用的是基于 Kafka Kraft 模式(KRaft Mode)的元数据管理架构。

最初 Kafka 使用 ZooKeeper 管理集群元数据,而 Kraft 模式则引入了内建的 Raft 协议控制器仲裁组(Controller Quorum)。该仲裁组由一组 Broker 组成,负责维护和确保元数据的一致性。

在 KRaft 模式下,每个 Broker 都持有元数据的本地副本,而控制器仲裁组的 Leader 负责元数据的修改与更新,并将这些变更同步到所有 Broker,从而降低了运维复杂度和潜在的故障点。

在 AutoMQ 中,控制器 Leader 保存了整个集群的元数据信息,包括 Partition 与 Broker 的映射关系。只有 Leader 才能修改这些元数据,其他 Broker 需通过与 Leader 通信来发起变更请求。元数据的变更会由控制器统一广播到所有 Broker,确保整个集群的一致性。

AutoBalancer:AutoMQ自平衡功能

The Goals

Goal 指的是用于指导 Kafka 集群优化与负载均衡的一组目标或约束条件。这些目标定义了具体要求,例如 Broker 间的负载分布、资源使用上限、Partition 副本策略以及延迟控制标准等。

与 Cruise Control 提供预设目标并允许用户自定义不同,AutoMQ 的自平衡功能 AutoBalancer 提供了一套简洁、稳定且经过充分验证的默认目标,无需用户额外配置。

每个目标都定义了一个阈值(Threshold)和一个可接受范围(Acceptable Range)。 例如,一个用于平衡 Broker 负载的目标可能设定 CPU 使用率阈值为 50%,接受范围为 ±20%,即 30% 到 70% 之间。只要指标落在该范围内,即认为达成 Goal 。AutoBalancer 将 Goal 分为两类:

ꔷ Detection Goals:用于检测资源使用是否超出限制,例如 CPU 或网络 I/O 超载;

ꔷOptimization Goals: 主要用于执行集群流量的重新分配(Cluster Traffic Rebalancing)。AutoMQ 将这类目标进一步细分为 Producer、Consumer 和每秒查询数(QPS, Query Per Second)三种类型,不同的均衡目标对应不同的性能指标。例如,Producer、和 Consumer 的 Balance Goal 旨在确保 Producer 和 Consumer 的流量在各个 Broker 之间分布合理,而 QPS 的 Balance Goal 则用于平衡 Broker 之间的请求处理能力。这些优化目标相互配合,提升了集群的整体稳定性和资源使用效率。

为了确保在执行优化目标后系统效果的稳定性,AutoMQ 会针对检测型目标和优化型目标分别精心设定阈值与范围。例如,收紧优化型目标的范围可以在目标执行后获得更精确的优化效果。

某些特定的 Goal 可能具有比其他目标更高的优先级。AutoMQ 按照优先级将 Goal 分为两类:

ꔷ **Hard Goal:**必须在任何情况下都满足的目标,例如限制单个 Broker 上的 Partition 数量,或设置 Broker 流量的上限;

ꔷ **Soft Goal:**在与 Hard Goal 冲突时可以被忽略的目标,例如流量均衡等目标。

在 Goal 管理方面,AutoMQ 使用数学模型对每个 Goal 进行建模。模型会根据特定的数学条件判断 Broker 是否满足对应的目标。在某些情况下,实现某个 Goal 的方式可能不止一种(例如,将某个 Partition 从 Broker A 迁移到 B 或迁移到 C 都可能有助于平衡集群流量),AutoMQ 会通过数学系统评估这些方案,并基于与 Goal 相关的参数对每个决策进行打分,最终执行得分最高的方案,从而实现最优决策。

组件

AutoBalancer 的实现主要包括以下三个核心组件:

ꔷ Metrics Collector(指标采集器):Apache Kafka 提供了基于 YammerMetrics 和 KafkaMetrics 的指标采集系统,可通过 MetricsRegistry 和 MetricsReporter 接口进行监控。基于这些接口,AutoMQ 实现了一个 Reporter,用于周期性采集预定义的指标(如网络流量吞吐量等)。AutoMQ 使用一个内部 Topic 在 Broker 与 Controller 之间传输指标数据;Reporter 在采集完指标后,会将其封装为多条 Message 并发送至该内部 Topic。

ꔷ State Manager(状态管理器):在 Controller 端,AutoMQ 维护一个 ClusterModel,用于表示当前集群状态和各个 partition 的负载情况。集群中发生的变化(如 Broker 的增加/移除,Partition 的重新分配或删除)会通过监听 KRaft 的元数据进行捕获,并同步更新 ClusterModel。与此同时,Controller 会持续消费内部 Topic 中的指标数据,对提取出的指标进行预处理,并更新 ClusterModel,确保其始终准确反映集群当前状态。

ꔷ Decision Scheduler(决策调度器):该组件的目标是帮助集群实现预期的调度效果,例如限制单个 Broker 上的 Partition 数量或控制单个 Broker 的流量。在 AutoMQ 中,仅有 Active Controller 负责执行决策与调度。决策开始前,AutoMQ 会对当前的 ClusterModel 进行快照,并基于该快照状态进行后续调度过程。快照完成后,ClusterModel 可继续更新。AutoMQ 的决策调度过程采用类似 Cruise Control 的启发式调度算法。

典型流程

接下来我们深入了解 AutoMQ 自平衡(Self-Balancing)的典型流程(Typical Process ):

ꔷ 每隔一个固定时间间隔(例如每 60 秒),自平衡调度器会启动一次,检查当前集群是否满足所有的 Goal。如果全部满足,调度器将进入休眠状态;

ꔷ 如果未满足,调度器会获取违反 Goal 的 Broker 列表;

ꔷ 对于每个不符合要求的 Broker,调度器会生成 Partition 重分配(Reassignment)计划,以尝试使该 Broker 满足对应的 Goal;

ꔷ 调度器随后会判断该重分配计划是否对该 Broker 可行。如果可行,调度器就会在集群上执行该计划;如果不可行,则认为该 Broker 当前无法满足 Goal,调度器将继续检查列表中的下一个 Broker。

应用场景

下面我们来回顾 AutoBalancer 在不同场景下的行为:

云计算环境中,"Rack" 可以指代一个可用区(Availability Zone)。

ꔷ Topic Creation:AutoBalancer 支持在 Topic 创建时进行机架感知( Rack Awareness )。它支持在多个 Rack 间随机分布数据的同时,考虑每个 Rack 的 " Weight "。权重大( Weight 较高)的 Rack 将比权重轻的 Rack 分配到更多的数据。在同一 Rack 内,数据也会依据 Broker 的权重分布,如果某个 Broker 的权重更高,它在该 Rack 内将获得更大的数据份额。

ꔷ Adding Brokers:AutoBalancer 支持对新增 Broker 进行逐步 "预热"。系统不会一下子将全部流量发送到新 Broker,而是会在一段时间内逐渐引导流量,以避免其负载过高。AutoBalancer 也会尽可能减少扩容过程中的跨 Rack 流量,以避免网络拥塞,除非涉及新增 Rack。

ꔷ Removing Brokers:AutoBalancer 支持在 Broker 被移除后自动迁移其负责的 Partition 到其他 Broker。它会优先尝试将 Partition 迁移到与原 Broker 属于同一 Rack 的其他 Broker。

ꔷ Unbalanced Throughput: 系统会根据各个 Broker 处理请求的能力分配流量。每个物理 Broker 拥有一个 " Weight ",表示其承载负载的能力。例如,更强大的 Broker 会被赋予更高的 Weight。AutoMQ 会综合考虑网络、IO 或 CPU 核心数等因素来评估 Broker 的 Weight。系统会持续监控每个节点的负载和处理能力,并根据情况调整调度策略,以防止某个 Broker 被过度使用。

ꔷ Single Node Failures: AutoBalancer 支持识别运行缓慢的 Broker,这类 Broker 可能存在潜在问题。系统可以通过将任务迁移至健康节点来降低这些慢节点的负载,从而在不影响整体性能的前提下让其恢复。

AutoBalancer 与 Cruise Control 对比

在结束本文之前,我们来回顾一下 AutoBalancer 与 Cruise Control 的一些区别:

ꔷ AutoMQ 原生支持 AutoBalancer 功能,无需进行复杂的运维操作和部署;相比之下,Cruise Control 需要独立部署并与 Kafka 集群配套管理。

ꔷ Apache Kafka 在进行 Partition 迁移以实现流量均衡时,需要复制大量数据,执行成本较高。因此,Cruise Control 的 Goal 设计较为严格,仅在流量波动较小的场景下效果较好。对于负载变化剧烈的场景,Cruise Control 难以保持有效。而 AutoMQ 通过其计算与存储分离的架构,更能应对复杂的负载变化场景。

ꔷ 得益于设计优势,AutoMQ 允许 AutoBalancer 更快速地执行 Replica 的重新分配。此外,由于 AutoBalancer 是 AutoMQ 的内建组件,它可以直接消费 KRaft 日志,从而能更快速地响应集群变更。

结语

感谢大家阅读本文。本文回顾了部分 Kafka 术语,例如 Partition Replica 如何在 Broker 之间分布,以及当集群成员发生变化时为何需要重新分配 Replica,并介绍了 Kafka 原生提供的 Replica 迁移方案。

随后,我们探讨了 Cruise Control 等第三方工具如何以更便捷和更稳健的方式辅助用户完成这一流程。我们发现,AutoMQ 能够彻底解决迁移过程中的数据移动难题,因为其数据存储在 Broker 之外,仅需调整 Metadata 即可完成迁移。

最后,我们深入介绍了 AutoMQ 的自平衡功能 ------ AutoBalancer。我们看到,虽然 Cruise Control 能够帮助用户更高效地完成 Kafka 的 Replica 重分配过程,但其核心问题依然存在:数据仍需在 Broker 间通过网络传输。而 AutoMQ 的创新架构使数据完全存储于对象存储中,大大简化了 Kafka 的许多操作,尤其是在 Partition 重新分配时,仅需调整 Metadata 即可完成,从而使其内部的自平衡机制更加高效可靠。

至此,本文即将结束。我们下次再见。

参考资料

1\] With the help of Kaiming Wan, Director of Solutions Architect \& Lead Evangelist @ AutoMQ \[2\] AutoMQ official documentation \[3\] AutoMQ blog \[4\] Confluent, Best Practices for Kafka Production \[5\] Kafka Cruise Control Github Repo

相关推荐
Ftrans3 小时前
【分享】文件摆渡系统适配医疗场景:安全与效率兼得
大数据·运维·安全
天氰色等烟雨6 小时前
支持MCP服务的多平台一键发布工具
大数据·github·mcp
AutoMQ6 小时前
技术干货|深度剖析将 Kafka 构建在 S3 上的技术挑战与最佳实践
大数据
搞数据的小杰8 小时前
spark广播表大小超过Spark默认的8GB限制
大数据·数据库·分布式·spark
isNotNullX8 小时前
数据怎么分层?从ODS、DW、ADS三大层一一拆解!
大数据·开发语言·数据仓库·分布式·spark
时序数据说9 小时前
时序数据库处理的时序数据独特特性解析
大数据·数据库·物联网·时序数据库·iotdb
专注VB编程开发20年9 小时前
WPF,Winform,HTML5网页,哪个UI开发速度最快?
大数据·c#·wpf
武子康11 小时前
大数据-42 Redis 发布/订阅详解:机制、弱事务性与实际风险分析
大数据·redis·后端
万能小锦鲤11 小时前
《大数据技术原理与应用》实验报告一 熟悉常用的Linux操作和Hadoop操作
大数据·linux·hadoop·ubuntu·vmware·实验报告·大数据技术原理与应用