3. Kafka 核心概念:Topic、Partition、Offset、Producer、Consumer、Broker

好,咱们进入 Kafka 的核心地带。说实话,Kafka 的概念并不多,但每个都挺关键。你如果搞懂了 Topic、Partition、Offset 这几个东西,Kafka 的底层逻辑基本就通了八成。我当年刚接触 Kafka 时,就是被这些概念绕晕过,后来自己动手搭了个集群,才真正明白它们是怎么配合的。

3.1 Broker:Kafka 的服务器节点

Broker 说白了就是一台运行着 Kafka 进程的服务器。一个 Kafka 集群由多个 Broker 组成,每个 Broker 有一个唯一的 ID(数字)。

我记得第一次搭集群时,只配了 3 个 Broker。当时觉得够用了,结果线上流量一上来,某个 Broker 磁盘直接打满。嗯,后来我才意识到,Broker 的数量和磁盘规划,直接决定了集群的吞吐上限。

核心要点:

  • 每个 Broker 独立存储一部分数据
  • Broker 之间通过 Zookeeper 或 KRaft 协调元数据
  • 客户端连接任意一个 Broker 就能获取整个集群的路由信息

3.2 Topic:数据的逻辑分类

Topic 是 Kafka 里最上层的抽象。你可以把它理解成数据库里的「表」,或者文件系统里的「文件夹」。生产者往 Topic 里写数据,消费者从 Topic 里读数据。

举个例子,我在做实时订单系统时,会建一个 order_topic。所有订单事件都往这个 Topic 里发。下游的实时风控、实时大屏、数据仓库,各自订阅这个 Topic 就行。一个 Topic,多方消费,互不干扰。

我的习惯:Topic 命名最好带上业务含义和环境标识。比如 order_event_prod、user_log_dev。别用 topic1、test 这种名字,不然三个月后你自己都看不懂。

3.3 Partition:并行与扩展的基石

Partition 是 Kafka 真正存储数据的地方。一个 Topic 可以分成多个 Partition,每个 Partition 是一个有序的、不可变的日志文件。

为什么要分区?说白了就是为了并行。你想想看,如果一个 Topic 只有一个 Partition,那无论你有多少个消费者,都只能串行读。但如果你有 6 个 Partition,理论上就可以用 6 个消费者并行消费,吞吐量直接翻 6 倍。

我在项目中遇到过一个问题:某个 Topic 的 Partition 数设得太少(只有 3 个),但下游有 10 个消费者实例。结果 7 个实例一直闲着,3 个实例忙到飞起。这就是典型的「分区数 < 消费者数」导致的资源浪费。

避坑指南:Partition 数一旦设定,虽然可以增加,但不能减少。我曾经在生产环境上误操作,想减少 Partition 数,结果 Kafka 直接报错。所以上线前一定要规划好 Partition 数,通常建议是 Broker 数量的 2-3 倍。

3.4 Offset:消息的唯一标识

Offset 是 Partition 内每条消息的唯一序号。它从 0 开始,单调递增。消费者读取消息时,需要记录自己消费到了哪个 Offset,这样下次重启才能接着读。

Offset 这个概念,我刚开始觉得很简单,不就是个数字嘛。但后来踩了个坑:消费者提交 Offset 的时机不对,导致重复消费了大量数据。那次事故让我记住了——Offset 的提交策略,直接决定了你的消费语义是「至少一次」还是「精确一次」。

Offset 的关键特性:

  • 每个 Partition 独立维护 Offset
  • Offset 只增不减,不会回退
  • 消费者可以手动指定 Offset 实现「回溯消费」

3.5 Producer:数据的生产者

Producer 负责把消息发送到 Kafka 的指定 Topic。它有几个关键参数直接影响性能和可靠性:

参数 作用 我的推荐值
acks 确认级别:0、1、all 生产环境用 all,保证不丢数据
retries 发送失败重试次数 3 次,配合幂等生产者使用
batch.size 批量发送的字节数 16KB-64KB,根据消息大小调整
linger.ms 批量发送前的等待时间 5-10ms,平衡延迟和吞吐

我个人习惯在 Flink 中作为 Producer 时,把 acks 设为 all,同时开启幂等。虽然会多一点点延迟,但换来的是数据不丢的保障。做实时计算,数据一致性永远是第一位的。

3.6 Consumer 与 Consumer Group

Consumer 从 Topic 拉取数据。但 Kafka 里更重要的概念是 Consumer Group(消费组)。同一个 Group 内的消费者,共同消费一个 Topic,每条消息只会被 Group 内的一个消费者处理。

举个例子:你有一个订单 Topic,下游有实时风控、实时推荐、数据仓库三个不同的业务。它们各自是一个独立的 Consumer Group。每个 Group 都能消费到全量数据,但 Group 内部的多个实例会分摊负载。

避坑经验:我曾经把两个不同业务的消费者放在了同一个 Group 里,结果发现其中一个业务永远收不到消息。排查了半天才意识到——同一个 Group 内的消费者是竞争关系,不是订阅关系。不同业务一定要用不同的 group.id。

3.7 核心关系一览

说了这么多,咱们用一张图把整个关系串起来。这张图我画了很多次,每次给团队新人讲 Kafka 时都会拿出来用。

Kafka 核心概念关系图 Producer Topic (逻辑分类) 例如:order_event_prod Partition 0 Partition 1 Partition 2 Offset(消息序号) Partition 0: offset 0, 1, 2, 3 ... Partition 1: offset 0, 1, 2, 3 ... Consumer Group(消费组) Consumer 1 Consumer 2 Consumer 3 Broker 集群(服务器节点) Broker 1 | Broker 2 | Broker 3 | ... 数据流向 1. Producer 写入 Topic 2. Topic 分散到多个 Partition 3. Partition 存储消息 + Offset 4. Consumer Group 拉取消费 5. 所有数据存储在 Broker 上

3.8 这些概念跟 Flink 有什么关系?

你可能会问,学这些跟 Flink 集成有什么关系?关系大了去了。

  • 并行度映射:Flink 的 Source 并行度,通常等于 Kafka Topic 的 Partition 数。你设多了浪费资源,设少了消费不过来。
  • Offset 管理:Flink 有自己的一套 Offset 提交机制,跟 Kafka 原生的不太一样。搞混了会导致数据重复或丢失。
  • Consumer Group:Flink 作业启动时,会自动注册一个 Consumer Group。如果多个 Flink 作业用了同一个 group.id,就会出现消费竞争。

一句话总结:Topic 是路,Partition 是车道,Offset 是里程碑,Producer 是发车的人,Consumer 是开车的人,Broker 是停车场。搞懂了这些,Kafka 你就入门了。