2. Kafka 核心概念再梳理:Topic、Partition、Offset、Consumer Group、ISR 机制、Leader 与 Follower 选举
好,咱们正式开始第二讲。这一章我打算把 Kafka 最核心的几个概念彻底捋一遍。很多同学学了几年 Kafka,问起来都知道 Topic、Partition,但真到了线上排查问题,往往就卡在细节上。
说白了,这些概念不是孤立的知识点。它们串在一起,才构成了 Kafka 高吞吐、高可用的底层逻辑。我习惯把它们分成三组来理解:存储模型(Topic/Partition/Offset)、消费模型(Consumer Group)、高可用模型(ISR/Leader-Follower 选举)。咱们一个一个来。
2.1 存储模型:Topic、Partition、Offset
先看 Topic。你可以把 Topic 理解成数据库里的一张表,或者一个消息的分类标签。生产者往 Topic 里写数据,消费者从 Topic 里读数据。但 Kafka 不会把整个 Topic 的数据放在一个文件里——那样单机磁盘根本扛不住。
所以就有了 Partition。每个 Topic 被切分成若干个 Partition,每个 Partition 是一个有序的、不可变的日志文件(Log)。Partition 是 Kafka 并行度的基本单位。你想想看,一个 Topic 如果有 3 个 Partition,那最多就能被 3 个消费者并行消费。
那 Offset 是什么?它是 Partition 内每条消息的唯一编号。从 0 开始,单调递增。消费者读完一条消息,会提交当前 Offset,表示“我已经读到这儿了”。下次重启,就从提交的 Offset 继续消费。
核心要点:Topic 是逻辑概念,Partition 是物理存储单元,Offset 是消息在 Partition 内的位置指针。三者缺一不可。
我记得有一次线上排查,发现某个 Topic 的消费延迟特别大。一看监控,Partition 数量只有 2,但消费者进程开了 4 个。白白浪费了 2 个线程。这就是典型的 Partition 数没规划好。
我的建议:Partition 数量一般设置为消费者组内最大并行度的 1~2 倍。太少会限制吞吐,太多会增加 Leader 选举和文件句柄开销。
2.2 消费模型:Consumer Group
Consumer Group 是 Kafka 实现点对点和发布订阅两种模式的关键。一个 Group 内,每个 Partition 只能被一个 Consumer 消费。但一个 Consumer 可以消费多个 Partition。
举个例子:假设 Topic 有 4 个 Partition,你的 Consumer Group 里有 3 个消费者。那分配结果可能是:Consumer-1 消费 P0、P1,Consumer-2 消费 P2,Consumer-3 消费 P3。如果 Group 里有 5 个消费者,那就会有 1 个消费者闲置。
| 场景 | Partition 数 | Consumer 数 | 结果 |
|---|---|---|---|
| 理想情况 | 4 | 4 | 每个 Consumer 消费 1 个 Partition,负载均衡 |
| Consumer 过多 | 4 | 6 | 2 个 Consumer 闲置,浪费资源 |
| Consumer 过少 | 4 | 2 | 每个 Consumer 消费 2 个 Partition,压力集中 |
这里有个坑:Rebalance。当 Group 内有消费者加入或退出时,Kafka 会触发 Rebalance,重新分配 Partition。Rebalance 期间,整个 Group 会停止消费。我曾经遇到过因为消费者频繁超时,导致 Group 每几分钟就 Rebalance 一次,消费延迟直接飙到小时级。
避坑指南:我曾经在生产环境遇到过 Consumer 心跳超时设置过短,加上 GC 停顿,导致频繁 Rebalance。后来把 session.timeout.ms 从 10 秒调到 30 秒,配合 max.poll.interval.ms 调大,问题才解决。
2.3 高可用模型:ISR 机制与 Leader/Follower 选举
这部分是 Kafka 高可用的核心。Kafka 通过副本(Replica)机制保证数据不丢。每个 Partition 可以有多个副本,分布在不同的 Broker 上。副本分为两种角色:Leader 和 Follower。
- Leader:负责处理所有读写请求。生产者只往 Leader 写,消费者只从 Leader 读。
- Follower:只从 Leader 拉取数据,保持同步。不对外提供服务。
那问题来了:如果 Leader 挂了,谁来接替?Kafka 不会随便选一个 Follower 当 Leader。它只从 ISR(In-Sync Replicas) 列表里选。
ISR 是什么? 是“与 Leader 保持同步的副本集合”。Follower 会定期向 Leader 发送拉取请求,如果某个 Follower 落后太多(超过 replica.lag.time.max.ms 配置的时间),就会被踢出 ISR。只有 ISR 里的副本,才有资格参与 Leader 选举。
关键点:ISR 机制保证了“选出来的新 Leader 一定拥有最新的数据”。如果所有副本都挂了,Kafka 会等待 ISR 中最后一个副本恢复,或者启用 unclean.leader.election.enable=true 允许非 ISR 副本当选(但会丢数据)。
Leader 选举的过程是这样的:
- Controller(Kafka 集群中的一个特殊 Broker)检测到 Leader 所在的 Broker 宕机。
- Controller 从 ISR 列表中选出一个 Follower 作为新 Leader。
- Controller 更新 ZooKeeper 中的元数据,并通知所有 Broker 新的 Leader 信息。
- 新 Leader 开始对外提供服务,Follower 继续从新 Leader 拉取数据。
我遇到过一种情况:某个 Broker 磁盘 I/O 飙升,导致 Follower 拉取数据变慢,被踢出了 ISR。结果 Leader 一挂,ISR 里只剩一个副本,选举虽然成功了,但整个集群的冗余能力降到了最低。后来我们加上了磁盘 I/O 告警,才避免类似问题。
我的经验:生产环境建议把 min.insync.replicas 设置为 2,配合 acks=all,保证至少有一个 Follower 确认写入。这样即使 Leader 挂了,ISR 里还有副本可以接替。
2.4 知识体系总览
下面这张图把本章的核心概念串了起来。你可以看到数据从生产者到消费者,中间经过了 Topic、Partition、副本、ISR 等环节。建议你保存下来,后面几章还会反复用到。
2.5 本章小结
这一章我们把 Kafka 的六个核心概念拆开揉碎了讲了一遍。你记住三句话就够了:
- Topic + Partition + Offset 决定了数据怎么存、怎么定位。
- Consumer Group 决定了数据怎么分、怎么消费。
- ISR + Leader/Follower 选举 决定了系统挂了怎么恢复、数据丢不丢。