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 依赖顺序的链路要评估重排影响。
保序只在单分区内成立:生产者重试、并发发送与消费者并行处理都可能打破全局顺序,需要严格顺序时通常还要配合幂等与单分区串行消费。