首页/数据/数据工程与 ETL 速查/消息 Key 与分区路由
Kafka64 条

消息 Key 与分区路由

带 key 的消息按 murmur2(key) % 分区数 选择分区,同 key 始终落同一分区从而保序;无 key 时按可用分区轮询(粘性分区会先填满一批再切换)。

Key 如何决定分区

生产者发送的每条消息可以带一个 key,默认分区器对 key 做 murmur2 哈希再对分区数取模,因此同一个 key 始终落在同一个分区上,而同一分区内的顺序是被保证的——这就是「按业务键保序」的实现方式。不带 key 时消息会按可用分区分发(较新版本采用粘性策略,先填满一批再切换),吞吐更均衡但没有顺序保证。

基本信息

带 key哈希取模,同 key 同分区,顺序有保证
无 key轮询/粘性分发,吞吐均衡但不保序
注意分区数变化会改变 key 到分区的映射
默认分区器客户端内置,可通过 partitioner.class 替换
保序范围仅保证单分区内有序,跨分区不保证
消费端并行并行度上限等于分区数

带 key 生产(控制台)

带 key 生产(控制台)
kafka-console-producer.sh --bootstrap-server localhost:9092 \
  --topic orders \
  --property parse.key=true \
  --property key.separator=:
# 输入:order-1001:{"amount": 9.9}

# 消费时打印 key 与分区,核对路由是否符合预期
kafka-console-consumer.sh --bootstrap-server localhost:9092 \
  --topic orders --from-beginning \
  --property print.key=true --property print.partition=true

典型使用场景

  • 同一实体的变更保序:用订单号或用户号做 key,保证事件按顺序被处理
  • 状态更新:下游按 key 归并最新值,避免旧状态覆盖新状态
  • 热点控制:key 分布均匀时负载均衡,分布集中时需要通过复合 key 打散
  • 无顺序要求的日志:不带 key 或按随机 key 分发,获取更高吞吐
  • 分区数规划:key 的取值基数决定可用的最大并行度上限

常见现象判读

现象原因处理
某分区流量远高于其他分区key 分布倾斜改用复合 key 或加随机后缀
同 key 顺序错乱分区数变化后映射改变评估重排影响或固定分区数
扩容后历史顺序断裂新旧映射不一致下游按时间戳二次排序
消费并行上不去分区数少于消费者数增加分区并接受映射变化
空 key 与空串行为不同null 走分发逻辑,空串参与哈希统一使用 null 或统一赋值
对同一业务键要求严格有序时,分区数扩容会打散既有映射;已按 key 依赖顺序的链路要评估重排影响。
保序只在单分区内成立:生产者重试、并发发送与消费者并行处理都可能打破全局顺序,需要严格顺序时通常还要配合幂等与单分区串行消费。

易错点

  • key 为 null 与空字符串的行为不同:null 走轮询逻辑,空串仍参与哈希
  • 自定义分区器要实现与旧版兼容的接口,升级客户端时注意废弃 API
  • 用高基数的 key(如每次请求生成唯一 ID)导致分区无法复用、顺序保证失效
  • 以为换了 key 就能解决热点,实际要考虑 key 的值分布是否均匀
  • 消费端用多线程并行处理同一分区的消息,破坏了原有的顺序语义

数据来源与参考

  • Apache Kafka 官方文档:Producer Configs(partitioner.class)与 DefaultPartitioner
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌