Kafka 为什么有 Topic 还要用 Partition?
结论:Topic 解决的是"逻辑分类"——按业务命名、按订阅授权、按保留策略管理;分区(Partition)解决的是"物理并行"——它才是日志文件、副本、顺序与并行消费的真实单位。没有分区,一个 Topic 就只能落在单机上,容量、吞吐、故障隔离全部受限于一台机器。
一、逻辑层与物理层
逻辑层:Topic "order-events" ← 业务只认这个名字
│
├── Partition 0 [broker-0] Leader=0 Follower=1,2 ← 1GB 日志段 × N
├── Partition 1 [broker-1] Leader=1 Follower=2,0
└── Partition 2 [broker-2] Leader=2 Follower=0,1
物理层:/data/kafka/order-events-0/00000000000000000000.log
/data/kafka/order-events-1/00000000000000000000.log
/data/kafka/order-events-2/00000000000000000000.log
| 关注点 | Topic 负责 | Partition 负责 |
|---|---|---|
| 命名与订阅 | 消费者订阅的粒度 | 消费者实际分配的单位 |
| 权限与配额 | ACL、生产/消费限流 | 无独立权限 |
| 保留与清理 | 统一 retention.ms | 每个分区独立日志段、独立删除 |
| 顺序 | 无保证 | 分区内严格有序 |
| 并行度 | 无 | 并行读写与并行消费的上限 |
| 副本 | 无 | 副本以分区为单位,Leader 逐分区选举 |
| 容量 | 无 | 可跨 Broker 横向扩展 |
二、分区解决了三个硬限制
- 单机容量:一个 Topic 的数据量可能到 TB 级,单机磁盘放不下,分区让数据分散到多台 Broker;
- 单机吞吐:单分区写入受限于单盘顺序写带宽与单 Leader 的网络,多分区可并行使用多台机器的 IO;
- 消费并行度:一个分区同一时刻只能分给组内一个消费者,分区数直接决定消费并行上限。
反过来说,分区也带来了代价:跨分区无序、分区数不能减少、分区过多会推高文件句柄与元数据开销。
三、分区数怎么估
| 估算维度 | 公式 | 示例 |
|---|---|---|
| 按吞吐 | 目标吞吐 ÷ 单分区吞吐(约 10~50MB/s) | 200MB/s ÷ 20MB/s = 10 |
| 按消费者 | 期望消费并行度(消费者数) | 计划 8 个消费者 → ≥ 8 |
| 按容量 | 日增数据量 ÷ 单分区可承受容量 | 1TB/天,单分区 200GB → ≥ 5 |
| 预留 | 取最大值再乘 1.5~2 倍余量 | 上述取 10 → 规划 15~20 |
分区只能增加不能减少,所以宁可略多,也不要事后频繁扩容(扩容会改变 key 的映射,破坏"同 key 同分区"的假设)。
四、创建与验证
# 建 12 分区、3 副本
kafka-topics.sh --bootstrap-server 10.0.0.31:9092 --create \
--topic order-events --partitions 12 --replication-factor 3
# 扩容到 24 分区(只能增)
kafka-topics.sh --bootstrap-server 10.0.0.31:9092 --alter \
--topic order-events --partitions 24
# 查看每个分区的 Leader、副本、ISR
kafka-topics.sh --bootstrap-server 10.0.0.31:9092 --describe --topic order-events
// 写入时指定 key,才能稳定落到同一分区
producer.send(new ProducerRecord<>("order-events", orderId, payload));
五、常见追问
- 为什么不直接把 Topic 当分区用(一个 Topic 一个分区)? 那所有消息都挤在单机上,既无法横向扩容,也无法并行消费;Topic 数量爆炸还会拖慢元数据管理。
- 分区数能减吗? 不能。减少分区等于删除数据并重排 key 映射,Kafka 只支持增加;要"缩容"只能新建 Topic 再迁移。
- 一个分区能被多个消费者消费吗? 同一消费组内不能,这是分区独占原则;不同消费组可以各自消费同一个分区(各自维护位点)。
- 分区越多吞吐越高吗? 到瓶颈后反而下降:副本同步线程、文件句柄、Controller 元数据、故障恢复时间都会随分区数增长。
小结
- Topic 是逻辑与治理单位,Partition 是存储、顺序、副本与并行的物理单位。
- 分区解决单机容量、单机吞吐、消费并行度三个上限。
- 分区数只能增不能减,规划要按吞吐、消费者数、容量三者取最大并留余量。
- 顺序与 key 路由都以分区为边界,扩容前必须评估对顺序语义的影响。