Skip to content

Kafka 分区怎么设计 ​

难度与前置

难度:入门
前置:知道消息按 key 哈希到分区;消费并行上限 ≈ 分区数。
读完能做什么:按吞吐、顺序、热点三维给 Topic 定分区键与分区数,并写清扩容与验收标准。

适用场景 ​

当你要新建业务 Topic或改造「单分区撑不住 / 热点分区打满」的旧主题时,用本篇定分区策略。

不适用:

  • 临时调试 Topic(单分区即可)
  • 已有强顺序契约且改键会破坏下游(先评迁移方案)
  • 吞吐极低、无 SLA 压力的内部流水

真实场景(一条) ​

投放事件 Topic 最初 3 分区,Flink 并行度 3。大促时入站 QPS×5,总 lag 高且 partition 1 占据 70% 流量(大客户 channel_id 哈希撞车)。扩消费者到 12 无效(受 3 分区限制)。

改法:评估顺序需求后改为 24 分区;分区键改为更均匀业务键或加盐;大客户单独 Topic。扩容后峰值可水平扩展,单分区字节占比回落到健康区间。

怎么做(步骤清单) ​

1. 先写三条约束 ​

约束问题例子
顺序是否要同 key 严格有序?同 user_id 的状态变更要有序
吞吐峰值消息/字节与目标延迟峰值 5 万条/s,延迟 < 30s
热点是否存在超级 key?头部渠道占总流量 40%

三者冲突时的默认优先级:业务正确的顺序 > 可解释的热点隔离 > 分区数凑吞吐。

2. 分区键怎么选 ​

键策略顺序保证风险适用
无 key(轮询)无无顺序日志采集、可乱序指标
user_id / device_id同用户有序头部用户热点用户行为流
order_id同订单有序一般较均匀订单事件
channel_id同渠道有序大渠道热点需渠道内有序时
hash(key)+salt破坏原顺序要二次聚合强热点打散

TIP

需要有序时:分区键 = 有序粒度;消费者端同分区单线程处理。
不需要有序时:宁可无 key 或加盐,也不要死守会热点的粗键。

3. 分区数估算 ​

text
分区数 ≥ max(
  峰值吞吐 / 单分区舒适吞吐,
  计划消费者最大并行度,
  未来 6~12 个月增长预留 ×1.5~2
)

常见起步:中小主题 6~12;主力实时明细 24~64;避免一上来上千分区。

4. 副本与其它 Topic 级参数 ​

bash
kafka-topics.sh --bootstrap-server ${brokers} --create \
  --topic ods_ad_spend_event \
  --partitions 24 \
  --replication-factor 3 \
  --config min.insync.replicas=2 \
  --config retention.ms=172800000 \
  --config compression.type=lz4
参数建议
replication-factor生产 ≥ 3
min.insync.replicas2(配合 producer acks=all)
保留时长覆盖补数窗口(如 2~7 天)
压缩lz4/zstd 按生态统一

5. 扩分区注意点 ​

  • 只能增不能减(常规)
  • 旧消息仍在旧分区;新 key 映射会变,同 key 跨扩容前后可能落到不同分区 → 跨边界顺序不保证
  • 扩容后同步调 Flink/消费者并行,并观察再均衡
  • 大改键:优先新 Topic + 双写/迁移,而不是原地赌命

6. 与消费者并行度对齐 ​

text
有效消费并行 ≈ min(应用并行度, 分区数)

Flink:source 并行度不要长期小于热点治理后的需求,也不要无脑大于分区数。

7. 设计评审检查单 ​

  • [ ] 有序粒度与分区键一致,并写进契约
  • [ ] 热点 key 有数据分布抽样
  • [ ] 分区数 ≥ 近一年并行规划
  • [ ] 副本与 ISR、保留时长满足补数
  • [ ] 扩容 / 改键迁移路径有负责人
  • [ ] 与 Flink / 消费组命名、DLQ 策略一并评审

8. 迁移路径(改键 / 扩容) ​

变更推荐路径
只扩分区扩容 → 调消费者并行 → 观察 lag 与再均衡
改分区键新 Topic → 双写 → 下游切读 → 停旧
大客户隔离独立 Topic + 路由,避免污染公共分区

常见坑(至少牢记这些) ​

  1. 按「机器核数」拍分区数,不问顺序与热点
    核数变了主题却不能减分区,历史包袱难清。

  2. 粗粒度业务键导致永久热点
    大渠道单分区打满,总分区再多也救不了该键。

  3. 扩分区当降 lag 唯一手段
    若根因是 Sink 反压,扩分区只是把火烧得更散。先看消费瓶颈类型。

  4. 改分区键不评迁移
    下游按「同分区有序」做的状态机会乱。改键=契约变更。

  5. replication=1 上生产
    Broker 宕机即丢未同步数据。生产至少 3 副本 + ISR 策略。

如何验收(可量化) ​

合并前 checklist,全勾才算本篇实践落地:

  • [ ] 设计文档写清:分区键、是否有序、分区数推导、保留与副本
  • [ ] 压测或线上峰值:单分区字节/消息占比无长期过高(如 > 30%)
  • [ ] 消费者并行度与分区数匹配策略有说明
  • [ ] 扩容演练:扩分区后消费正常、lag 可回落
  • [ ] 若有序:抽同 key 消息在单分区内顺序校验通过
  • [ ] 热点大户有隔离方案(加盐 / 独立 Topic)或书面接受风险
bash
kafka-run-class.sh kafka.tools.GetOffsetShell \
  --broker-list ${brokers} --topic ods_ad_spend_event --time -1
sql
SELECT channel_id, COUNT(*) AS cnt
FROM ods_ad_spend_detail_di
WHERE dt = '${biz_date}'
GROUP BY channel_id
ORDER BY cnt DESC
LIMIT 20;

与 Lag / 反压的关系 ​

分区不够或热点时,Kafka 积压排查 会表现为少数分区堆积;盲目扩消费者无效。若 Sink 反压,先读 Flink 反压,再决定是否扩分区。

上线后一周内复盘一次单分区占比,超阈值则启动加盐或拆题。

附:上线检查口头禅 ​

键是否高基数、分区数是否留余量、消费并行度能否对齐、有序语义是否写清、扩容是否做过演练——五项过完再切流量。高峰后再观察至少一个完整业务周期,确认无新的热点分区与 rebalance 风暴。

相关面试题 ​

占位:与题库小程序对齐后补链接(建议关联:分区与并行度、有序消费、再均衡、热点打散)。


改写说明:结构与判断标准参考 Wood 原创数仓/面试文,已改写成可执行清单;未包含未公开公司数据与内部表名。