逻辑结构
┌───────────────────────────────────────────────────────────
│ Kafka Cluster │
│ │
│ ┌---------- Broker-1 ----------┐ ┌---------- Broker-2 ----------┐
│ | Topic-A |
│ | partition-0 LEADER (ISR={0,1}) partition-1 FOLLOWER |
│ | partition-2 FOLLOWER partition-0 LEADER(...) |
│ └------------------┬-------------------┘ └------------------┬--------┘
│ │ 心跳/元数据/控制器(Controller) │
└─────────────────────┼─────────────────────────────────────
核心概念速记
- Cluster 是集群,多台服务器
- Broker 是节点,比如(192.168.0.1 192.168.1.1)
- Topic 逻辑消息主题,类似数据库表
- Partition 是Topic 的物理分片,顺序与并行的最小单元,可以理解为管道或者队列
- Replica 分区副本
- Consumer Group 消费者组,组内分区独占,组间广播
创建 Topic
powershell
./kafka-topics.sh \
--bootstrap-server localhost:9092 \
--create \
--topic order-topic \
--partitions 3 \
--replication-factor 1
解释:
- order-topic Topic名称
- partitions=3 创建3个Partition, Partition 编号:0、1、2
- replication-factor 1 表示该主题的每个分区只保存一份数据,没有副本,--replication-factor 1,意味着该主题的每个分区只有 Leader,没有任何 Followe
查看 Topic
perl
./kafka-topics.sh \
--bootstrap-server localhost:9092 \
--describe \
--topic order-topic
输出类似:
perl
Topic: order-topic
PartitionCount: 3
Partition:0
Partition:1
Partition:2
创建生产者
perl
./kafka-console-producer.sh \
--bootstrap-server localhost:9092 \
--topic order-topic \
--property parse.key=true \
--property key.separator=:
解释 :
- property "parse.key=true" 启用消息的键值解析模式。默认情况下,生产者只发送消息体(值)。加上该参数后,控制台会读取用户输入的每一行,并按分隔符拆分为键(Key)和值(Value)
- property "key.separator=:" 指定键与值之间的分隔符为冒号 :。结合上一行,当你在控制台输入类似 order123:{"id":1} 的内容时,order123 会被作为消息的 Key,而 {"id":1} 作为消息的 Value 发送到 Kafka。
输入
perl
order123:{"status":"CREATED"}
order123:{"status":"PAID"}
order456:{"status":"CREATED"}
Kafka 默认分区路由规则(重点)
perl
partition = hash(key) % numPartitions
把key进行hash,再对Partitions的数量取模
你的消息会进哪个 Partition?
perl
Key hash(key) %3 进哪个 Partition
order123 hash1 1 ✅ Partition-1
order123 hash1 1 ✅ Partition-1
order456 hash2 0 ✅ Partition-0
结论
- ✅ order123的两条消息 一定在同一个队列
- ✅ order456在另一个队列
- ✅ 顺序性得到保证(按 key)
当你再发 4 个不同 Key 时会发生什么?
perl
order4:{"status":"CREATED"}
order6:{"status":"CREATED"}
现在你有 4 个 Key,3 个 Partition
perl
Key hash %3 Partition
order123 h1 1 P1
order456 h2 0 P0
order4 h3 2 P2
order6 h4 1 P1
结果
- 多个 Key 一定会共用同一个 Partition
- 这不是 Bug,而是 设计如此
- Kafka 不会为每个 Key 单独建
Partition
如何让「指定消息」进入「指定队列」?
这样 所有消息强行进 Partition-2(⚠️ 一般不推荐,破坏均衡)。
perl
bin/kafka-console-producer.sh \
--bootstrap-server localhost:9092 \
--topic order-topic \
--property parse.key=true \
--property key.separator=: \
--property partition=2
Kafka 的三种分区路由方式
(1)直接指定 Partition
bash
bin/kafka-console-producer.sh \
--bootstrap-server localhost:9092 \
--topic order-topic \
--property parse.key=true \
--property key.separator=: \
--property partition=2
解释: 将所有消息全部放入Partition-2
(2) 自定义 Partitioner
比如:
- 订单号末位 → Partition
- 城市编码 → Partition
- 业务类型 → Partition
java
java
public class OrderPartitioner implements Partitioner {
@Override
public int partition(String topic, Object key, byte[] keyBytes,
Object value, byte[] valueBytes, Cluster cluster) {
int numPartitions = cluster.partitionCountForTopic(topic);
if ("order456".equals(key)) {
return 0; // 强制进 partition 0
}
// 其他 key 走默认 hash
return Math.abs(Utils.murmur2(keyBytes)) % numPartitions;
}
@Override public void close() {}
}
(3)Key-based Hash(默认策略)
bash
partition = hash(key) % partitions
那为什么大家"以为 Kafka 只能用 Hash"?
因为这是 99% 的业务用法

如果key是null进入那个partition ?
你的操作顺序
bash
# 1️⃣ 创建 topic(3 partitions)
./kafka-topics.sh \
--bootstrap-server localhost:9092 \
--create \
--topic order-topic \
--partitions 3 \
--replication-factor 1```
```bash
# 2️⃣ 启动 producer(开启 key)
./kafka-console-producer.sh \
--bootstrap-server localhost:9092 \
--topic order-topic \
--property parse.key=true \
--property key.separator=:
最终输出
bash
order1:{"status":"CREATED"}
order2:{"status":"PAID"}
order3:{"status":"CREATED"}
{"status":"CREATED"}


黏性分区
bash
kafka-console-producer.sh \
--bootstrap-server localhost:9092 \
--topic order-topic \
--property parse.key=true \
--property key.separator=:
输入
bash
order1:{"status":"CREATED"} ✅ Key 有值 → Hash → P1
order2:{"status":"PAID"} ✅ Key 有值 → Hash → P2
order3:{"status":"CREATED"} ✅ Key 有值 → Hash → P0
{"status":"CREATED"} ❌ Key 为 null → Sticky → P0
发生什么?
- 发完 order3后,Producer 当前粘住的 Partition 是 P0
- 接着发 key=null的消息✅ 直接复用 P0
- 不换 Partition,不重新选