本文是大数据系列第 53 篇,深入拆解 Kafka 三大核心组件的工作原理与协作流程。

完整图文版(含截图):CSDN 原文 | 掘金

整体架构回顾

Kafka 是一个分布式发布-订阅消息系统,三大核心角色分工明确:

Producer(生产者)
    ↓ 发布消息
Broker 集群(消息存储与路由)
    ↓ 消费消息
Consumer Group(消费者组)

三者通过 Topic + Partition 解耦:Producer 只管发布,Consumer 只管订阅,Broker 负责中间的持久化与路由。

Producer:消息生产者

基本职责

Producer 负责创建消息并发布到指定 Topic。发送流程:

  1. 序列化消息(Key/Value)
  2. 根据分区策略选择目标 Partition
  3. 将消息追加到本地缓冲区(RecordAccumulator
  4. 后台 Sender 线程批量发送到对应 Broker

分区策略

策略触发条件效果
指定分区发送时显式指定 partition精确路由
Hash 分区指定消息 Key相同 Key 始终写同一 Partition,保证局部有序
轮询分区无 Key 时默认均匀分布,最大化吞吐
自定义分区器实现 Partitioner 接口业务自定义路由逻辑

ACK 确认机制

acks 参数控制消息可靠性与吞吐的权衡:

acks 值语义适用场景
0不等待任何确认,即发即忘日志收集,允许少量丢失
1Leader 写入成功即确认默认值,均衡可靠性与性能
all-1所有 ISR 副本写入后确认金融、订单等核心数据

异步发送示例

ProducerRecord<Integer, String> record =
    new ProducerRecord<>("my_topic", 0, 42, "hello kafka");

// 异步发送,通过回调处理结果
producer.send(record, (metadata, exception) -> {
    if (exception == null) {
        System.out.println("Sent to partition " + metadata.partition()
            + " at offset " + metadata.offset());
    } else {
        exception.printStackTrace();
    }
});

Broker:消息存储节点

核心职责

Broker 是 Kafka 集群的基本单元,每个 Broker 是一个独立 JVM 进程,负责:

  • 接收 Producer 写入的消息,持久化到本地磁盘
  • 响应 Consumer 的拉取请求
  • 维护 Partition 的 Leader/Follower 角色
  • 与 ZooKeeper(或 KRaft)协调集群元数据

Partition 的物理存储

每个 Partition 对应磁盘上的一个目录,内部由多个 Segment 文件组成:

/var/kafka-logs/my_topic-0/
├── 00000000000000000000.log     ← 消息数据文件
├── 00000000000000000000.index   ← 偏移量稀疏索引
└── 00000000000000000000.timeindex ← 时间戳索引
  • 文件名是该 Segment 起始 Offset 的 20 位补零数字
  • 写入时 Append-only,读取时通过二分查找索引定位 Offset
  • 默认单个 Segment 超过 1GB 或 7 天后滚动生成新 Segment

Leader 与 Follower

Partition Leader(在某个 Broker 上)
    ← 接收 Producer 写入
    → 响应 Consumer 读取
    → 异步推送给 Follower 同步

Partition Follower(在其他 Broker 上)
    → 从 Leader 拉取消息,追上 Leader 进度
    → 进入 ISR 列表
    → Leader 故障时,从 ISR 中选举新 Leader

Controller 角色

集群中有且仅有一个 Broker 担任 Controller,通过 ZooKeeper 选举产生:

  • 监控 Broker 存活状态
  • 负责 Partition Leader 选举
  • 管理 Partition 的 ISR 列表变更
  • 协调新 Broker 加入时的 Partition 重新分配

Consumer:消息消费者

Consumer Group 机制

Kafka 通过 Consumer Group 实现两种消费语义:

同一 Group 内:           不同 Group 间:
  Partition 1 → Consumer A   Group A → 各自消费
  Partition 2 → Consumer B   Group B → 各自消费
  Partition 3 → Consumer C   (发布-订阅语义)
(点对点语义)

关键规则

  • 每个 Partition 在同一 Consumer Group 内只能被一个 Consumer 消费
  • Consumer 数量超过 Partition 数时,多余的 Consumer 闲置
  • Consumer 退出/加入时触发 Rebalance,重新分配 Partition

Offset 管理

Consumer 通过 Offset 跟踪消费进度:

方式说明
自动提交enable.auto.commit=true,每隔 auto.commit.interval.ms 自动提交
手动同步提交consumer.commitSync(),确保消费成功后提交,避免消息丢失
手动异步提交consumer.commitAsync(),性能更高,但失败时不重试

Offset 存储在 Kafka 内部 Topic __consumer_offsets 中(Kafka 0.9+ 之后不再依赖 ZooKeeper)。

消费位置重置

通过 auto.offset.reset 控制消费者首次启动或 Offset 丢失时的行为:

  • earliest:从 Partition 最早的消息开始消费
  • latest(默认):只消费启动后新产生的消息
  • none:不存在已提交 Offset 时抛出异常

Rebalance 触发条件

触发 Rebalance 的情形:
  1. Consumer 加入 Group(新实例上线)
  2. Consumer 离开 Group(崩溃或正常下线)
  3. Consumer 超时未发送心跳(session.timeout.ms)
  4. Topic Partition 数量变化

Rebalance 期间所有消费者暂停消费,生产环境应合理配置 session.timeout.msmax.poll.interval.ms 减少不必要的 Rebalance。

消息全流程梳理

1. Producer 序列化消息,选定 Partition
2. Producer 将消息批量发送到目标 Broker(Leader)
3. Leader Broker 将消息写入本地日志(.log 文件)
4. Follower 主动从 Leader 拉取新消息,写入本地副本
5. ISR 中所有副本确认写入后,消息视为"已提交"
6. Consumer 向 Leader 发起 Poll 请求,携带当前 Offset
7. Leader 返回从该 Offset 开始的消息批次
8. Consumer 处理完成后提交新 Offset

小结

  • Producer 的分区策略和 ACK 机制决定消息路由和可靠性
  • Broker 的 Segment 存储和 ISR 机制保障高性能持久化和高可用
  • Consumer Group 通过 Partition 独占分配实现并行消费,Offset 管理控制消费语义
  • 三者协同,构成 Kafka 高吞吐、低延迟、高可用的完整闭环