Kafka 核心原理回顾:Topic 与 Partition 机制、Producer/Consumer 模型、Broker 与 Controller、ISR 与 ACK 机制
说实话,很多做实时数据采集的同学,对 Kafka 的理解停留在「发消息、收消息」的层面。一旦 Topic 数量上去、分区数调大、数据出现积压,就开始抓瞎了。
我个人习惯是,不管项目多急,先把 Kafka 这几个核心机制吃透。你想想看,元数据采集的本质就是跟 Topic、Partition、Broker 打交道,如果底层原理不清楚,后面配参数、调优、排错根本无从下手。
这一章,咱们就把 Kafka 的骨架拆开来看。不扯虚的,全是实战中天天要面对的东西。
2.1 Topic 与 Partition 机制
Topic 是 Kafka 里最基础的数据组织单元。你可以把它理解成数据库里的一张表,或者文件系统里的一个文件夹。但 Kafka 跟传统消息队列最大的区别在于——Topic 可以被拆成多个 Partition。
核心观点:Partition 是 Kafka 并行度的基本单位。一个 Topic 的 Partition 数越多,理论上吞吐量就越高。但凡事有代价——Partition 太多,元数据管理、Leader 选举、文件句柄的开销都会暴涨。
我在项目中遇到过这么个坑:有个业务方把 Topic 的分区数设成了 1000,结果集群 Broker 只有 3 台。每台 Broker 要管理 300 多个分区,Leader 频繁重选举,整个集群的 ISR 抖动得厉害。后来我强制要求:分区数不要超过 Broker 总数的 10 倍,除非你有充分的理由。
Partition 内部的数据是有序的,通过偏移量(Offset)来标识每条消息的位置。但跨 Partition 就不保证顺序了。这一点很多新手会搞混。
| 概念 | 说明 | 实战注意点 |
|---|---|---|
| Topic | 逻辑上的消息分类 | 命名规范要统一,建议用「业务线.数据域.表名」 |
| Partition | 物理上的存储分片 | 分区数 = max(消费者线程数, 预期吞吐量 / 单分区吞吐量) |
| Offset | 分区内消息的唯一序号 | Offset 不会全局唯一,只在分区内递增 |
| Segment | Partition 的物理文件片段 | 默认 1GB 滚动一次,频繁滚动会影响 IO |
我的习惯:创建 Topic 时,先把分区数设成 Broker 数的 3 倍。比如 5 台 Broker,分区数先给 15。后面根据实际流量再调整。Kafka 2.4+ 支持在线扩分区,但缩分区不行,所以起步别贪多。
2.2 Producer 模型
Producer 负责把数据发到 Kafka。看起来简单,但里面的门道不少。
Producer 的核心流程是这样的:
- 应用调用
send()方法 - 序列化器把对象转成字节数组
- 分区器决定数据发到哪个 Partition
- 数据进入缓冲区(默认 32MB)
- Sender 线程批量发送到 Broker
这里有个关键点——send() 方法是异步的。很多人以为调用 send() 就发出去了,其实数据还在缓冲区里。如果缓冲区满了,send() 会阻塞,或者抛异常。
我曾经遇到过一个线上事故:有个采集任务突然积压了几百万条数据,查了半天发现是 Producer 的 buffer.memory 设得太小,加上 max.block.ms 设成了 60 秒,导致应用线程全堵在 send() 上。后来我把缓冲区调到 128MB,问题就解决了。
Producer 还有一个重要的参数——acks。这个咱们放到后面跟 ISR 一起讲。
避坑指南:千万不要在 Producer 的回调函数里做耗时操作。我曾经见过有人在回调里写数据库,结果回调线程池被打满,整个 Producer 都卡死了。回调里只做轻量级的统计和日志,重操作另起线程。
2.3 Consumer 模型
Consumer 是消费端。Kafka 的 Consumer 跟传统消息队列最大的不同是——Consumer 主动拉数据,而不是 Broker 推数据。
这样做的好处很明显:Consumer 可以自己控制消费速度,不会把消费者压垮。但坏处是,如果 Consumer 拉得太慢,数据就会积压。
Consumer 的核心机制是「消费者组」(Consumer Group)。同一个组内的消费者共同消费一个 Topic,每个 Partition 只能被组内的一个消费者消费。
举个例子:Topic 有 6 个 Partition,消费者组里有 3 个 Consumer。理想情况下,每个 Consumer 分到 2 个 Partition。但如果 Consumer 数超过 Partition 数,多出来的 Consumer 就闲着。
| 场景 | Partition 分配情况 | 说明 |
|---|---|---|
| Consumer = Partition | 1:1 分配 | 最理想的情况 |
| Consumer < Partition | 部分 Consumer 消费多个 Partition | 吞吐量够用,但负载不均 |
| Consumer > Partition | 部分 Consumer 空闲 | 浪费资源,需要调整 |
我建议你在设计消费者组时,Consumer 数不要超过 Partition 数。多出来的 Consumer 不仅没用,还会增加 Rebalance 的开销。
说到 Rebalance,这是 Consumer 最让人头疼的地方。一旦有 Consumer 加入或退出,整个组都要重新分配 Partition。这个过程会暂停消费,如果 Topic 分区数多,Rebalance 可能持续几十秒。
我的经验:用静态消费组(Static Group Membership)可以避免不必要的 Rebalance。把 group.instance.id 设成固定值,Consumer 重启时就不会触发 Rebalance。这个功能在 Kafka 2.3+ 开始支持。
2.4 Broker 与 Controller
Broker 就是 Kafka 的服务器节点。一个集群通常有 3 台以上的 Broker。
Broker 之间不是完全对等的。有一个特殊的角色叫 Controller,它负责管理整个集群的元数据。
Controller 的职责包括:
- 管理 Partition 的 Leader 选举
- 处理 Broker 的上下线
- 维护集群的元数据信息
- 通知其他 Broker 更新元数据
Controller 是通过 Zookeeper 选举出来的。第一个在 Zookeeper 上创建临时节点的 Broker 就是 Controller。如果 Controller 挂了,其他 Broker 会重新选举。
我遇到过一个问题:集群里有个 Broker 网络不稳定,频繁上下线。每次上下线,Controller 都要触发 Leader 重选举,导致整个集群的写入延迟飙升。后来我们给 Broker 加了心跳超时检测,把 zookeeper.session.timeout.ms 从 6 秒调到了 18 秒,情况才稳定下来。
注意:Controller 是单点的。虽然挂了可以重新选举,但在选举期间,集群的元数据操作(比如创建 Topic、扩分区)会不可用。所以 Controller 所在的 Broker 要选硬件最好、网络最稳定的那台。
2.5 ISR 与 ACK 机制
这两个概念是 Kafka 可靠性的基石。说白了,就是「数据到底安不安全」的问题。
ISR(In-Sync Replicas),就是跟 Leader 保持同步的副本集合。只有 ISR 里的副本,才有资格在 Leader 挂了之后接替它。
Kafka 判断一个副本是否在 ISR 里,标准很简单:副本跟 Leader 的差距不能超过 replica.lag.time.max.ms(默认 10 秒)。如果副本落后太多,就会被踢出 ISR。
ACK 机制是 Producer 端的配置,用来控制数据写入的可靠性级别。
| ACK 值 | 行为 | 可靠性 | 性能 |
|---|---|---|---|
| acks=0 | Producer 发完就不管了 | 最低,可能丢数据 | 最高 |
| acks=1 | Leader 写入成功就返回 | 中等,Leader 挂了可能丢 | 较高 |
| acks=all | 所有 ISR 副本都写入成功才返回 | 最高,不会丢数据 | 较低 |
我在做实时元数据采集时,一律用 acks=all。为什么?因为元数据丢了,后面所有数据治理、血缘分析全得完蛋。性能损失可以通过调整 batch.size 和 linger.ms 来弥补。
但要注意,acks=all 不代表 100% 不丢数据。如果 ISR 里只剩一个 Leader 副本,那跟 acks=1 其实没区别。所以还要配合 min.insync.replicas 参数,强制要求 ISR 里至少有几个副本。
推荐配置:
- Topic 副本数:3
- min.insync.replicas:2
- Producer acks:all
这样即使一台 Broker 挂了,数据也不会丢。
2.6 核心知识体系总览
说了这么多,咱们用一张图把 Kafka 的核心机制串起来。这张图我每次培训都会用,你把它记在脑子里,后面学元数据采集会轻松很多。
这张图把 Kafka 的核心流程串起来了:Producer 发数据到 Topic 的 Partition,Partition 分布在多个 Broker 上,每个 Partition 有 Leader 和 Follower,ISR 保证数据一致性,Consumer 从 Leader 拉数据。Controller 负责协调整个集群。
嗯,这一章的内容就到这里。Kafka 的核心机制是后面所有元数据采集方案的基础。你把这些搞清楚了,后面讲 Kafka Connect、Schema Registry、元数据变更捕获的时候,就不会觉得吃力了。