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 时都会拿出来用。
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 你就入门了。