2. Kafka 核心概念速览:Topic、Partition、Producer、Consumer、Broker、Offset
好,咱们直接进入正题。Kafka 这东西,说白了就是一个「分布式消息队列系统」。但跟传统的 RabbitMQ、ActiveMQ 不一样,它的设计哲学更偏向「日志」和「流」。我刚开始接触时也被一堆概念搞晕过,后来发现只要抓住六个核心词,整个架构就通了。
这六个词就是:Topic、Partition、Producer、Consumer、Broker、Offset。它们之间的关系,我习惯用一张图来理解。
一句话总结:Producer 往 Topic 里写数据,Topic 被切成多个 Partition 分散存到不同的 Broker 上,Consumer 从 Partition 里按 Offset 顺序读数据。
2.1 Broker —— 集群里的每一台机器
Broker 就是 Kafka 的服务器节点。一个 Kafka 集群由多个 Broker 组成,每个 Broker 有一个唯一的 ID。说白了,它就是存数据、扛读写的那台物理机或容器。
我记得第一次搭集群时,只配了 3 台 Broker,心想「够用了吧」。结果线上流量一上来,某台 Broker 的磁盘直接打满。后来我才意识到,Broker 的数量直接决定了集群的吞吐上限和容错能力。
我的建议:生产环境至少 3 个 Broker 起步。如果对可用性要求高,Broker 数量最好是奇数,配合 ZooKeeper / KRaft 做选举时更顺畅。
2.2 Topic —— 数据的逻辑分类
Topic 就像数据库里的「表」,或者文件系统里的「文件夹」。你把同一类消息都发到同一个 Topic 里。比如订单数据发到 order_topic,用户行为发到 user_behavior_topic。
但 Topic 本身不存数据。它只是一个逻辑名字。真正存数据的地方,是下面要说的 Partition。
2.3 Partition —— 真正存数据的地方
一个 Topic 会被分成多个 Partition。每个 Partition 是一个有序的、不可变的日志文件(append-only log)。新消息永远追加到文件末尾。
为什么要分 Partition?两个原因:
- 并行:多个 Partition 可以分散到不同 Broker 上,读写可以并行。
- 水平扩展:Topic 数据量大了,加 Partition 就行,不用停机。
我遇到过一个问题:有人把 Topic 只设了 1 个 Partition,结果 Consumer 再多也只能串行消费,吞吐死活上不去。你想想看,这就好比一条单车道,车再多也只能一辆一辆过。
注意:Partition 内的消息是有序的,但跨 Partition 的消息不保证全局有序。如果你要求严格有序,要么只用 1 个 Partition,要么在 Producer 端按 key 哈希路由到同一个 Partition。
2.4 Offset —— 消息在 Partition 里的位置
每条消息写入 Partition 后,都会获得一个递增的、唯一的编号,这就是 Offset。你可以把它理解成「数组下标」或者「书签」。
Consumer 读数据时,不是像传统队列那样「取走就删除」。Kafka 的设计是:消息保留在磁盘上,Consumer 自己维护 Offset。想重读?把 Offset 重置到之前的位置就行。
我曾经帮一个团队排查数据丢失问题。他们发现 Consumer 重启后丢了一部分数据。查了半天,原来是 Consumer 的 Offset 提交时机不对——每次处理完消息就自动提交,结果处理逻辑还没跑完就挂了。嗯,这里要注意:Offset 提交的语义(自动 vs 手动、同步 vs 异步)直接影响数据一致性。
| 提交方式 | 说明 | 适用场景 |
|---|---|---|
| 自动提交(enable.auto.commit=true) | Consumer 每隔 auto.commit.interval.ms 自动提交 | 允许少量重复、对实时性要求高的场景 |
| 手动同步提交 | 处理完业务逻辑后调用 commitSync() | 需要精确一次语义、不能丢数据的场景 |
| 手动异步提交 | 调用 commitAsync(),不阻塞主线程 | 高吞吐、能接受偶发重复的场景 |
2.5 Producer —— 数据的生产者
Producer 负责把消息发到指定的 Topic。它有几个关键行为:
- 选择 Partition:可以指定 key,Kafka 对 key 做哈希决定发到哪个 Partition;不指定 key 则轮询。
- 确认机制(acks):
acks=0发完不管;acks=1等 leader 确认;acks=all等所有副本确认。 - 重试与幂等:开启
enable.idempotence=true可以避免网络重试导致的消息重复。
我个人习惯在生产环境把 acks 设为 all,配合幂等 Producer。虽然延迟会高一点点,但换来的是「不丢不重」的安心感。
2.6 Consumer 与 Consumer Group —— 数据的消费者
Consumer 从 Partition 拉取数据。多个 Consumer 可以组成一个 Consumer Group,共同消费一个 Topic。
这里有个关键机制:一个 Partition 只能被同一个 Group 内的一个 Consumer 消费。如果 Group 内的 Consumer 数量超过 Partition 数量,多出来的 Consumer 会闲置。
举个例子:Topic 有 4 个 Partition,Group 内有 3 个 Consumer。那么 3 个 Consumer 各分到 1 个 Partition,还剩 1 个 Partition 没人消费。如果 Group 内有 5 个 Consumer,那只有 4 个能干活,1 个闲着。
核心原则:Consumer Group 内的 Consumer 数量 ≤ Topic 的 Partition 数量,才能充分利用并行能力。
2.7 六个概念的关系总结
最后,我用一个表格把这六个概念串起来,方便你对照记忆:
| 概念 | 一句话解释 | 我踩过的坑 |
|---|---|---|
| Broker | Kafka 服务器节点,集群的物理载体 | 磁盘打满导致整个 Partition 不可用 |
| Topic | 消息的逻辑分类,类似数据库表名 | Topic 命名不规范,运维查问题全靠猜 |
| Partition | Topic 的物理分片,存数据的日志文件 | Partition 数设太少,Consumer 并行度上不去 |
| Offset | 消息在 Partition 内的唯一递增序号 | 自动提交导致重启后重复消费或丢数据 |
| Producer | 发送消息到 Topic 的客户端 | acks=0 时网络抖动丢消息,排查半天 |
| Consumer | 从 Partition 拉取消息的客户端 | Group 内 Consumer 数超过 Partition 数,白白浪费资源 |
这六个概念,是理解 Kafka 所有高级特性的地基。后面的章节里,我们会反复用到它们。你先把这张表记熟,后面讲分区策略、副本机制、消息可靠性时,就不会觉得乱了。