首页 / 资讯中心 / 文章详情

Kafka分区副本分配规则:从默认算法到机架感知

Kafka分区副本分配规则:从默认算法到机架感知 ★ FEATURED ARTICLE
1. 一个集群问题的起点分区副本分配决定了流量布局一开始我以为是我的监控脚本出了问题。某次我在维护一个模拟业务集群业务方反馈“订单写入变慢”我进到 Kafka 监控面板一看三个数据节点里有两个负载正常一个节点磁盘 IO 长期贴满 80% 以上。我的第一反应是磁盘老化或者硬件差异结果把硬件查了个遍最后才发现自己推错了方向——真正的差异出在 topic 的副本布局上也就是“Kafka 分区副本分配规则”上。1.1 分区副本分配真正决定的三件事Kafka 的 topic 会被切成多个分区每个分区又有若干副本。这些副本分别落在哪几台 broker 上就是标题里说的“分区副本分配规则”。可以这么理解副本分配决定了三件根本性的事情——数据放在哪、哪一份接受读写、以及当某台机器挂掉之后数据从哪继续服务。它同时还决定了一层几乎每个人都踩过的隐性问题热点。这里要先铺垫一个基础概念。在 Kafka 内部一个分区的多个副本里只有一个能接收读写请求叫 leader 副本其余的是 follower只能异步拉取 leader 的数据来同步。所以你看一台 broker 的负载本质上是这个节点上所有 leader 副本的读写压力总和而不是这个节点上所有副本的数量总和。分配规则不仅要考虑“副本均匀落在哪些 broker”还要考虑“leader 均匀落在哪些 broker”。这两个问题在默认分配逻辑里是同一套规则的两个侧面很多人只盯着前者回头排查热点的时候就会绕一大圈。再举个例子假设一个 topic 有 10 个分区、3 个副本、3 台 broker那么每台 broker 上都会有 10 个副本因为副本总数是 30平均每台 10 个表面上看起来完全均匀。但如果你把每个分区的 leader 都分配到同一台 broker 上那这台 broker 承担的读写流量就是另外两台的好几倍。这就是为什么“分配规则”不只是一个建 topic 时一次性执行的动作而是后续所有性能排查的出发点。1.2 先记住这个顺序约定再谈一切算法关于副本分配还有一个特别容易被忽视的约定每个分区对应的 broker 列表是有顺序的。列表里的第一个 broker 叫首选副本preferred replica正常情况下它就是这个分区的 leader后续位置则代表了故障转移时的备选顺序。这个顺序约定贯穿了我后面要讲的全部内容。默认分配算法在生成副本列表时会严格按这个顺序输出手动分配时你也必须按这个语义来写数组。许多人把副本列表当成一个无序集合来处理结果在看 leader 分布时总是一头雾水其实只要把“第一位是首选 leader”这个规则刻在脑子里很多现象立刻就能解释清楚。这篇内容我会从默认分配算法的执行细节讲起然后覆盖机架感知、扩容后的失衡、手动分配和实际集群里的验证方法。适合人群很明确需要自己创建 topic、维护多节点集群、处理过“某台 broker 莫名其妙变成热点”问题的同学。看完之后你应该能回答三个问题默认规则到底把我的副本放到了哪它为什么这样放以及当默认结果不能满足需求时有哪些工具和手段可以覆盖它。2. 默认分配算法到底做了什么环形递增与优先副本在继续之前先明确一个很多资料一笔带过、但实际很关键的细节Kafka 创建 topic 时会由分配器计算每个分区的副本列表。分配器接收的参数包括 broker 列表、分区数、副本数还可能包括机架信息。返回的结果是一个二维结构每个分区对应一组有序的 broker 编号。2.1 无机架场景从起始索引开始向右轮询无机架参数时分配逻辑可以简化成一句话从 broker 列表中的某个起始位置开始每向前处理一个分区就把起始下标加一然后在 broker 总数上循环取余。第 n 个分区的 leader 放在起始下标加 n 的位置第 i 个副本放在起始下标加 n 再加 i 的位置。需要特别提醒的是这个起始位置不是一个固定的 0而是一个随机数。分配器实现里通常会通过随机数生成起始索引然后所有分区的放置都基于这个随机索引进行偏移。这样设计的目的是避免每个 topic 创建时都从 broker 0 开始分配导致编号靠前的 broker 更容易累积“第一个分区”。如果所有 topic 都用同一个固定起点低编号 broker 会慢慢攒出一大批副本热点就是这么形成的。我再用一个完整例子说明。假设有 6 台 broker分别叫 B0 到 B5创建一个 3 副本的 topic连续看 12 个分区的分布。为了便于观察规律这里把随机起始索引固定为 0分区副本位置按数组顺序P0B0, B1, B2P1B1, B2, B3P2B2, B3, B4P3B3, B4, B5P4B4, B5, B0P5B5, B0, B1P6B0, B1, B2P7B1, B2, B3P8B2, B3, B4P9B3, B4, B5P10B4, B5, B0P11B5, B0, B1这个表格里的顺序不是乱排的第一个 broker 是该分区的首选副本后面依次是 follower。这里能看到两个规律。第一每个分区的相邻副本在 broker 列表中步进 1所以副本集合看起来是“连续重叠”的相邻分区会共享大部分 broker这个特点在 broker 故障时能让负载分散得更自然。第二leader 也是在所有 broker 之间轮转的P0 在 B0、P1 在 B1、P2 在 B2……读写流量天然就被分散开不会因为某个节点连续承担多个分区的 leader 而形成热点。2.2 为什么副本顺序会决定 leader有人可能觉得数组顺序无所谓反正副本之间可以随时切换。这里有一个容易被忽略的重要设计Kafka 的协调机制会尽力让每个分区的 leader 回到数组中的第一个副本。当 broker 重启、分区重新选举或者做了滚动升级之后你经常会在监控指标里看到“preferred replica election”这个概念它的含义就是把 leader 推回数组首位。如果数组顺序是随便写的那么 leader 切换之后流量分布就会飘掉。这也是很多集群在不做任何扩容、不改变副本数量的情况下渐渐出现“某台 broker 上的 leader 数量明显偏高”的原因。默认分配算法把 leader 按轮询顺序放得很均匀但后续的故障恢复和手动操作可能打破这个均匀布局所以生产集群通常会开启自动 leader 均衡让协调器定期把 leader 推回首选副本。所以当你用管理工具查看一个 topic 的详细分配时请务必把每个分区的 broker 列表看成一个有序列表而不是一个无序集合。第一个位置代表 leader 的期望位置这个顺序是后续所有选主操作的基石。把这条记牢了后面看手动分配和迁移工具的时候会特别顺。3. 机架感知分配故障域隔离比“数字均匀”更重要副本分配的第二条关键规则是机架感知rack awareness。我见过很多集群副本分布从数量上看完全均匀每台 broker 上的副本数几乎一样但一次机架断电就能让整个系统不可用原因就是分配时压根没考虑机架维度。3.1 机架信息如何影响分配器行为如果创建 topic 时没有给 broker 配置机架分配器只能把所有 broker 当成同一个故障域来处理。默认情况下所有 broker 的机架字段为空效果等同于它们都在同一个默认机架。这时候任何机架级别的故障都可能把某个分区的所有副本全部打掉。你在建 topic 之后回头查副本列表会发现某个分区的三个副本好巧不巧全落在同一个机架上这在物理上等于没有冗余。正确的做法是在 broker 的配置文件里加上机架标识比如 frankie 好的博主我需要基于标题Kafka分区副本分配规则为你生成一篇独立、完整的Kafka分区副本分配规则技术博文现在开始创作。
阅读完成 · 觉得有帮助?
咨询建站