Skip to content

分区数选择 ​

分区数是一个"选了就很难改"的决策。太少限制并行度,太多增加运维成本。本文给出选型依据和扩展风险。

1. 分区数决定了什么 ​

维度分区数的影响
消费并行度分区数 = 消费并行度的天花板
生产并行度多分区可以并行写入不同 Broker
故障恢复开销Broker 故障时需为大量分区重新选举 Leader,分区副本越多控制面开销越大
Controller 压力元数据管理开销随分区数增长
文件句柄每个分区对应多个文件

2. 选型依据 ​

并发数只是分区数的下限之一,不能单独决定分区数。分区数由三个维度共同约束,取其中最大值:

txt
分区数 ≥ max(写入所需分区数, 消费所需分区数, 消费者并行数)
  • 写入容量:目标写入吞吐 ÷ 单分区可持续写入能力。单分区写入能力受消息大小、复制因子、acks 配置影响,不是固定常量。
  • 消费容量:目标消费吞吐 ÷ 单分区可持续消费能力,保证分区总数足以承载消费吞吐。
  • 消费并行度:需要同时工作的消费者数量,机制见 分区与 Offset。

消费容量回答「分区能不能装下吞吐」,消费并行度回答「能不能让足够多的消费者同时干活」。两者不等价:多挂一个消费者不必然提高吞吐,还要看分区分配、单分区处理能力和下游瓶颈。

三个维度都满足后,最终配置还要结合 Broker 资源上限和实测结果校验。

以 KB 级消息、复制因子 3 的典型业务为例,分区数的经验数量级大致是:低吞吐 3~6、中等吞吐 10~30、高吞吐 50~100。这些数字随消息大小和复制因子变化很大,仅用于判断当前分区是否明显偏多或偏少,不能当作容量公式。

3. 分区过多的代价 ​

分区数量与分区副本总数是两个概念,实际开销取决于副本总数。以下按资源类型区分:

代价说明
文件句柄多每个分区副本对应多个文件(.log, .index, .timeindex)
内存占用增加每个分区副本的索引和缓冲区消耗内存
复制流量增加副本总数增加通常会增加副本维护开销和潜在复制负载,实际流量取决于写入速率、消息大小与 ISR 状态

故障恢复要区分两个阶段:单个分区的 Leader 选举开销很小;Broker 故障会同时触发大量分区重新选举、元数据更新和副本恢复,恢复时间取决于受影响的分区副本数量与控制面、数据面负载,不存在统一的固定阈值。排查见 Broker 故障。

如果分区副本总数过大导致恢复变慢,先检查是否分区过量、副本数是否需要收敛,而不是简单追加分区。

4. 分区扩展 ​

分区数只能增加、不能减少。

bash
kafka-topics.sh --alter --topic my-topic --partitions 12 --bootstrap-server localhost:9092

扩展风险 ​

风险说明
Key 路由变化默认哈希分区逻辑下,新增分区改变取模结果,同一 Key 的新消息可能进入不同分区,跨分区无序
消费者 Rebalance分区数变化触发 Rebalance
数据倾斜新分区没有历史数据,短期内数据不均衡

带 Key 的消息在默认哈希分区逻辑下,按序列化后的 Key 与当前分区数取模决定目标分区;无 Key 的消息走粘性分区,不受取模变化影响。扩容不会迁移历史消息,旧消息留在原分区,同一业务实体的新旧消息因此可能分散到不同分区,即使单分区内部有序,跨分区也没有顺序保证。使用自定义分区器或稳定分片映射时不适用上述结论。

扩展前的检查清单 ​

  1. 该 Topic 是否依赖 Key 的顺序性?如果是,扩展分区会破坏顺序
  2. 消费者组中有多少个消费者?扩展后是否需要增加消费者
  3. 是否在低峰期执行?扩展会触发 Rebalance,影响消费
  4. 扩容前先确认瓶颈在分区并行度而非消费者处理速度,判断方法见 消费者 Lag 过大

5. 分区数 vs 消费者数 ​

同一消费者组内,一个分区同一时刻至多分配给一个消费者,但消费者与分区不必一一对应。

txt
消费者数 < 分区数:每个消费者负责多个分区
消费者数 > 分区数:多余的消费者空闲,不参与消费

消费者数量由处理能力、分区分配和故障恢复时间要求共同决定,不等于「分区数减一」。需要故障后快速恢复时,应通过实例部署和消费组协调设计冗余,而不是多挂一个消费者当热备——同一组内新增消费者会直接参与分区分配,不会自动处于待命状态。

Released under the MIT License.