
90%的Kafka新手都会踩这个坑:消息发出去了,要么分区负载严重不均(有的分区消息堆成山,有的空着),要么同一类消息乱序(列如同一个用户的操作日志散落在不同分区)。
实则问题出在“分区策略”没选对——轮询和按key分区,看似简单,选错了可能直接影响系统性能和业务逻辑。
3分钟看懂两者区别,附实操代码,再也不用纠结!
简单说,分区策略就是“消息分配规则”——当生产者发送消息到一个多分区的Topic时,Kafka根据什么规则把消息放到哪个分区(列如Topic有3个分区,消息1放分区0?消息2放分区1?)。
核心作用有两个:
最常用的两种策略:轮询(Round-Robin) 和按key分区(Key-Based)。
就像发扑克牌,你一张、我一张、他一张——消息按顺序依次分配到各个分区,每个分区轮流接收消息。
消息1 → 分区0
消息2 → 分区1
消息3 → 分区2
消息4 → 分区0
消息5 → 分区1
...(循环往复)// 生产者配置(默认轮询策略)
Properties props = new Properties();
props.put("bootstrap.servers", "broker0:9092,broker1:9092");
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
Producer<String, String> producer = new KafkaProducer<>(props);
// 发送消息时不指定key,触发轮询策略
producer.send(new ProducerRecord<>("log-topic", null, "用户A登录")); // 分区0
producer.send(new ProducerRecord<>("log-topic", null, "用户B下单")); // 分区1
producer.send(new ProducerRecord<>("log-topic", null, "用户C支付")); // 分区2就像公司归档文件,“技术部”的文件全放1号柜,“市场部”的全放2号柜——消息会根据指定的“key”(如用户ID、订单号)分配到固定分区,同一key的消息必定在同一个分区。
Kafka会对key做哈希计算(hash(key) % 分区数),得到分区编号,因此同一key的哈希值一样,必然分到同一个分区:
key=用户A → hash(A)=100 → 100%3=1 → 分区1
key=用户A → hash(A)=100 → 100%3=1 → 分区1(同一用户消息在同一分区)
key=用户B → hash(B)=200 → 200%3=2 → 分区2 // 其他配置同上,发送消息时指定key
Producer<String, String> producer = new KafkaProducer<>(props);
// key=用户ID,同一用户的消息会到同一分区
producer.send(new ProducerRecord<>("order-topic", "user100", "用户100下单")); // 分区X
producer.send(new ProducerRecord<>("order-topic", "user100", "用户100支付")); // 分区X(和上一条同分区)
producer.send(new ProducerRecord<>("order-topic", "user200", "用户200下单")); // 分区Y维度 | 轮询策略(无key) | 按key分区(有key) |
负载均衡 | ✅ 优秀(绝对平均) | ⚠️ 可能失衡(依赖key分布) |
消息顺序 | ❌ 同一类消息无序 | ✅ 同一key消息有序 |
适用场景 | 日志、监控等无顺序需求场景 | 订单、用户轨迹等有顺序需求场景 |
配置难度 | ✅ 零配置(默认) | ⚠️ 需要合理设计key |
典型问题 | 无法保证同类消息顺序 | 热点分区(需优化key) |
1、按key分区如何避免热点?
2、需要全局顺序怎么办?
3、新手提议
你项目中用的哪种分区策略?有没有遇到过热点分区或消息乱序的坑?评论区分享你的解决方案,帮更多人避坑~
(下一篇讲“Kafka重平衡”,关注不迷路!)