Topic 管理
定义与作用
Topic 是 Kafka 中消息的逻辑分类单元。类比关系数据库中的"表"——不同的业务数据发送到不同的 Topic。本节使用 kafka-topics.sh 脚本完成 Topic 的创建、查看、修改和删除操作。
核心原理
Topic 的创建过程涉及 Controller 在多个 Broker 上分配 Partition 和 Replica:
完整示例
示例一:Topic 生命周期管理(CRUD)
操作前环境:Kafka 已启动,无用户自定义 Topic。
步骤:
# ===== CREATE =====
# 创建一个 3 分区、2 副本的 Topic
bin/kafka-topics.sh --create \
--topic orders \
--partitions 3 \
--replication-factor 2 \
--bootstrap-server localhost:9092
# Created topic orders.
# ===== LIST =====
# 列出所有 Topic
bin/kafka-topics.sh --list --bootstrap-server localhost:9092
# __consumer_offsets ← 内部 Topic,存储 Consumer Offset
# hello-world
# orders
# ===== DESCRIBE =====
# 查看 Topic 详情
bin/kafka-topics.sh --describe --topic orders --bootstrap-server localhost:9092
# Topic: orders TopicId: xxxxx PartitionCount: 3 ReplicationFactor: 2
# Partition: 0 Leader: 1 Replicas: 1,2 Isr: 1,2
# Partition: 1 Leader: 2 Replicas: 2,3 Isr: 2,3
# Partition: 2 Leader: 3 Replicas: 3,1 Isr: 3,1
# ===== ALTER =====
# 增加分区数(注意:只能增加,不能减少)
bin/kafka-topics.sh --alter \
--topic orders \
--partitions 6 \
--bootstrap-server localhost:9092
# ===== DELETE =====
# 删除 Topic
bin/kafka-topics.sh --delete \
--topic orders \
--bootstrap-server localhost:9092
操作后验证:
# 验证删除
bin/kafka-topics.sh --list --bootstrap-server localhost:9092
# __consumer_offsets
# hello-world
# orders 已消失
示例二:查看 Topic 消息数与消费者 Lag
场景:生产环境中需确认 Topic 是否有消息堆积。
步骤:
# 1. 查看每个 Partition 的起始 Offset
bin/kafka-run-class.sh kafka.tools.GetOffsetShell \
--topic hello-world \
--time -2 \
--bootstrap-server localhost:9092
# hello-world:0:0
# 2. 查看每个 Partition 的最新 Offset
bin/kafka-run-class.sh kafka.tools.GetOffsetShell \
--topic hello-world \
--time -1 \
--bootstrap-server localhost:9092
# hello-world:0:3
# 3. 消息数 = 最新 - 起始 = 3 - 0 = 3 条
操作前后对比:
| 指标 | 操作前 | 操作后(Producer 发 3 条后) |
|---|---|---|
| Topic 数量(不含内部) | 0 | 1(hello-world) |
hello-world 分区数 | — | 1 |
hello-world 消息数 | — | 3 |
kafka-topics.sh 参数速查
| 操作 | 参数 | 说明 |
|---|---|---|
| 创建 | --create --topic <name> --partitions <n> --replication-factor <m> | n ≤ Broker 数,m ≤ Broker 数 |
| 列表 | --list | 列出所有 Topic |
| 详情 | --describe --topic <name> | 显示 Partitions / Leader / ISR |
| 修改 | --alter --topic <name> --partitions <n> | 只能增加分区,不能减少 |
| 删除 | --delete --topic <name> | 需 Broker 配置 delete.topic.enable=true |
| 指定 Broker | --bootstrap-server <host:port> | Kafka 3.x 推荐,替代 --zookeeper |
易错场景
易错 1:分区数只能增不能减
场景:创建 Topic 时 --partitions 10,后来发现只需要 3 个分区。
错误做法:
bin/kafka-topics.sh --alter --topic mytopic --partitions 3
# ERROR: The number of partitions for a topic can only be increased
原因:减少分区意味着消息需要重新分配,这会破坏"同一 Key 的消息路由到同一分区"的语义保证。
解决:分区数规划时保守估计,创建后只能增加。如需减少,只能删除 Topic 重建(会丢失数据)。
易错 2:副本数不能超过 Broker 数
现象:
bin/kafka-topics.sh --create --topic test --partitions 1 --replication-factor 3
# Error: Replication factor 3 larger than available brokers: 1
原因:每个副本必须位于不同的 Broker 上(否则单机故障会导致两个副本同时丢失,副本机制失去意义)。
解决:单机开发环境设置 --replication-factor 1。
面试高频考点
Q:Topic 的分区数可以动态增加,为什么不能动态减少?如果要减少怎么办?
A:不能减少的原因是分区减少会破坏数据一致性——已写入的数据需要重新路由,而 Kafka 的消息顺序保证是基于分区的,减少分区会导致消息乱序。如果确实需要减少:
- 创建新 Topic(目标分区数)
- 通过 Kafka MirrorMaker 或自定义 Consumer→Producer 程序迁移数据
- 下线旧 Topic