Topic管理:从创建到运维的实战心法

Topic是Kafka里最核心的数据载体。说白了,你集群里跑的所有消息,最终都落在某个Topic的分区里。我刚开始接触Kafka时,觉得Topic不就是建个名字嘛,后来线上踩了几次坑才明白——Topic的创建、分区分配、副本机制,每一步都藏着门道。

这一章,我把这些年管理Topic的经验掰开揉碎讲给你听。咱们从最基础的创建删除开始,再到分区副本的底层逻辑,最后聊聊手动重分配这种高阶操作。

Topic的创建与删除

创建Topic有两种方式:自动创建和手动创建。生产环境我强烈建议你关掉自动创建。

注意: 自动创建Topic虽然方便,但会带来两个问题:一是分区数和副本数不可控,二是容易产生大量废弃Topic。我曾经接手过一个集群,自动创建导致几千个单分区Topic散落在集群里,管理成本极高。

手动创建的命令很简单:

# 创建一个名为"order-events"的Topic,6个分区,3个副本
bin/kafka-topics.sh --create \
  --bootstrap-server localhost:9092 \
  --topic order-events \
  --partitions 6 \
  --replication-factor 3 \
  --config retention.ms=604800000 \
  --config max.message.bytes=1048576

这里有几个参数我重点说一下:

  • partitions:分区数决定了并行处理能力。我一般建议分区数是消费者组内消费者数的整数倍,最好是2-3倍。
  • replication-factor:副本数。3副本是生产环境的标配,既能保证高可用,又不会浪费太多存储。
  • --config:可以覆盖Topic级别的配置。比如retention.ms控制数据保留时间,max.message.bytes控制单条消息大小。

删除Topic要小心:

# 删除Topic
bin/kafka-topics.sh --delete \
  --bootstrap-server localhost:9092 \
  --topic order-events
警告: 删除Topic会直接清空所有数据,且不可恢复。我建议你在删除前先确认三点:1) 确认没有消费者在消费该Topic;2) 确认数据已经备份或过期;3) 先在测试环境演练一遍。

分区与副本机制

分区是Kafka实现水平扩展的基石。每个分区都是一个有序的日志文件,消息按顺序追加。副本则是保证数据不丢的关键。

咱们来看一张分区副本的结构图:

Topic 分区与副本结构 Topic: order-events Partition 0 Partition 1 Partition 2 Leader (Broker 1) Follower (Broker 2) Follower (Broker 3) Leader (Broker 2) Follower (Broker 3) Follower (Broker 1) Leader (Broker 3) Follower (Broker 1) Follower (Broker 2) 每个分区有1个Leader和多个Follower,Leader负责读写,Follower负责同步 Leader宕机后,ISR中的Follower会选举为新的Leader

这张图展示了一个3分区、3副本的Topic。每个分区都有一个Leader副本和两个Follower副本。Leader负责处理客户端的读写请求,Follower则从Leader同步数据。

核心要点:
  • Leader和Follower分布在不同的Broker上,保证单点故障时数据不丢
  • ISR(In-Sync Replicas)是跟Leader保持同步的副本集合
  • 只有ISR里的副本才有资格被选举为新的Leader

分区分配策略

创建Topic时,Kafka需要决定每个分区的Leader和Follower放在哪些Broker上。这就是分区分配策略干的事。

Kafka默认的策略是轮询分配。举个例子,3个Broker、6个分区、3副本:

分区 Leader Follower 1 Follower 2
Partition 0 Broker 1 Broker 2 Broker 3
Partition 1 Broker 2 Broker 3 Broker 1
Partition 2 Broker 3 Broker 1 Broker 2
Partition 3 Broker 1 Broker 2 Broker 3
Partition 4 Broker 2 Broker 3 Broker 1
Partition 5 Broker 3 Broker 1 Broker 2

你看,每个Broker上的Leader数量是均匀的(2个),Follower数量也是均匀的(4个)。这种策略的好处是负载均衡,坏处是没考虑机架感知。

小技巧: 如果你的集群跨多个机架或数据中心,建议开启机架感知(rack awareness)。这样Kafka会尽量把副本分散到不同机架,避免一个机架断电导致所有副本丢失。配置方式是在broker的server.properties里设置broker.rack参数。

手动分区重分配

集群跑久了,难免会遇到负载不均的情况。比如新加了Broker,或者某个Broker磁盘快满了。这时候就需要手动做分区重分配。

我遇到过最典型的情况:集群从3台扩容到6台,结果新Broker上空空如也,老Broker上压力山大。手动重分配就是用来解决这个问题的。

操作步骤分三步:

  1. 生成分配计划:用kafka-reassign-partitions.sh生成一个JSON文件,描述每个分区的新位置。
  2. 执行分配:提交计划,Kafka会逐步把分区迁移到新位置。
  3. 验证结果:确认所有分区都迁移完成。

来看一个实际例子。假设我要把Topic "order-events" 的Partition 0从Broker 1迁移到Broker 4:

# 1. 生成分配计划
cat > reassign-plan.json << EOF
{
  "version": 1,
  "partitions": [
    {
      "topic": "order-events",
      "partition": 0,
      "replicas": [4, 2, 3]
    }
  ]
}
EOF

# 2. 执行分配
bin/kafka-reassign-partitions.sh \
  --bootstrap-server localhost:9092 \
  --reassignment-json-file reassign-plan.json \
  --execute

# 3. 验证进度
bin/kafka-reassign-partitions.sh \
  --bootstrap-server localhost:9092 \
  --reassignment-json-file reassign-plan.json \
  --verify
注意: 分区重分配会触发数据复制,对网络和磁盘IO有较大压力。我建议你在业务低峰期操作,并且控制并发迁移的分区数。可以通过--throttle参数限制迁移速度,比如--throttle 50000000(50MB/s)。

还有一个常见场景:Leader分布不均。有时候虽然副本分布均匀,但Leader都集中在某几个Broker上。这时候可以用优先副本选举来重新平衡Leader:

# 对所有Topic执行优先副本选举
bin/kafka-leader-election.sh \
  --bootstrap-server localhost:9092 \
  --election-type preferred \
  --all-topic-partitions

这个操作不会移动数据,只是把Leader切换回优先副本(即副本列表中的第一个)。速度很快,对集群影响小。

总结一下我的经验:
  • 创建Topic时,分区数要预留扩展空间。我一般按未来6个月的数据量估算,再乘以1.5的系数。
  • 副本数3是黄金标准,别为了省磁盘设成2,也别浪费资源设成4以上。
  • 手动重分配是运维利器,但一定要限速、限并发、选低峰期。
  • 定期检查Leader分布,用优先副本选举保持负载均衡。

嗯,Topic管理这块内容不少,但核心就是这几板斧。你把这些搞透了,日常运维基本不会出大问题。