Kafka 入门第一篇:核心概念与整体架构
Kafka 入门第一篇:核心概念与整体架构
🎯 目标读者:有Java基础,第一次接触Kafka
📖 难度:⭐⭐☆☆☆
⏱️ 预计阅读时间:20 分钟
一、Kafka 是什么?
Apache Kafka 是一个由 LinkedIn 开源、后捐献给 Apache 基金会的分布式流处理平台。
用一句话概括它的核心能力:
Kafka 是一个高吞吐、低延迟、可持久化、可水平扩展的分布式消息系统。
1.1 它能解决什么问题?
想象一个电商系统:用户下单后,需要同时触发以下操作:
- 扣减库存
- 发送短信通知
- 更新用户积分
- 通知物流系统
- 记录用户行为日志
没有 Kafka 时(同步调用):
sequenceDiagram
participant 用户
participant 订单服务
participant 库存服务
participant 短信服务
participant 积分服务
participant 物流服务
用户->>订单服务: 下单请求
订单服务->>库存服务: 扣库存(同步)
订单服务->>短信服务: 发短信(同步)
订单服务->>积分服务: 加积分(同步)
订单服务->>物流服务: 通知物流(同步)
订单服务-->>用户: 返回成功(等待所有完成后)
问题:响应慢、系统耦合、一个服务挂了全挂。
有了 Kafka 后(异步解耦):
sequenceDiagram
participant 用户
participant 订单服务
participant Kafka
participant 库存服务
participant 短信服务
participant 积分服务
用户->>订单服务: 下单请求
订单服务->>Kafka: 发布"订单创建"事件
订单服务-->>用户: 立即返回成功
Kafka-->>库存服务: 异步消费
Kafka-->>短信服务: 异步消费
Kafka-->>积分服务: 异步消费
优势:响应快、解耦、各服务独立失败不影响核心链路。
二、Kafka 的核心概念
2.1 六大核心角色
graph TB
subgraph Kafka集群
B1[Broker 1]
B2[Broker 2]
B3[Broker 3]
end
subgraph Topic-订单事件
direction LR
P0["Partition 0\n[offset 0][offset 1][offset 2]..."]
P1["Partition 1\n[offset 0][offset 1][offset 2]..."]
P2["Partition 2\n[offset 0][offset 1][offset 2]..."]
end
Producer["🖊️ Producer\n(生产者)"] -->|写入消息| P0
Producer -->|写入消息| P1
Producer -->|写入消息| P2
P0 --> B1
P1 --> B2
P2 --> B3
B1 -->|推送/拉取| C1["Consumer A\n(消费者组1)"]
B2 -->|推送/拉取| C1
B3 -->|推送/拉取| C2["Consumer B\n(消费者组2)"]
ZK["🐘 ZooKeeper/KRaft\n(集群协调)"] -.->|元数据管理| B1
ZK -.->|元数据管理| B2
ZK -.->|元数据管理| B3
| 概念 | 说明 | 类比 |
|---|---|---|
| Broker | Kafka 服务节点,负责存储和转发消息 | 邮局 |
| Topic | 消息的逻辑分类,类似数据库的表 | 邮箱的分类 |
| Partition | Topic 的物理分片,实现并行处理 | 邮筒(多个) |
| Offset | 消息在 Partition 内的唯一序号(从0开始,单调递增) | 信件编号 |
| Producer | 向 Topic 发送消息的客户端 | 寄信人 |
| Consumer | 从 Topic 拉取消息的客户端 | 收信人 |
2.2 Topic 与 Partition
Topic 是一个逻辑概念,真正的数据存储在 Partition 中。
Topic: order-events
├── Partition 0 → 存储在 Broker 1(Leader)+ Broker 2(Follower)
├── Partition 1 → 存储在 Broker 2(Leader)+ Broker 3(Follower)
└── Partition 2 → 存储在 Broker 3(Leader)+ Broker 1(Follower)
为什么要分区?
- 水平扩展:多个 Partition 分布在不同 Broker 上,突破单机存储瓶颈
- 并行处理:Consumer Group 中的多个 Consumer 可以并行消费不同 Partition
- 高可用:每个 Partition 有多个副本(Replica),Leader 宕机后自动切换
2.3 Offset —— Kafka 的"书签"
Offset 是消息在 Partition 中的位置标记,单调递增、不可修改。
Partition 0 的消息布局:
┌────────┬────────┬────────┬────────┬────────┐
│Offset 0│Offset 1│Offset 2│Offset 3│Offset 4│
│ msg1 │ msg2 │ msg3 │ msg4 │ msg5 │
└────────┴────────┴────────┴────────┴────────┘
↑
Consumer 当前读到这里(offset=3)
⚠️ 重点:Kafka 不删除已消费的消息,消息保留时间由配置决定(默认7天)。这意味着同一条消息可以被多个 Consumer Group 独立消费。
2.4 Consumer Group —— 消费者组
Consumer Group 是 Kafka 消费模型的核心设计:
graph LR
subgraph Topic-3个Partition
P0[Partition 0]
P1[Partition 1]
P2[Partition 2]
end
subgraph 消费者组A-3个Consumer
CA1[Consumer A-1]
CA2[Consumer A-2]
CA3[Consumer A-3]
end
subgraph 消费者组B-1个Consumer
CB1[Consumer B-1]
end
P0 --> CA1
P1 --> CA2
P2 --> CA3
P0 --> CB1
P1 --> CB1
P2 --> CB1
规则:
- 同一个 Consumer Group 内,一个 Partition 只能被一个 Consumer 消费
- 不同 Consumer Group 之间互相独立,都能消费全量消息
- Consumer 数量 > Partition 数量时,多余的 Consumer 会闲置
2.5 ZooKeeper 与 KRaft
- ZooKeeper(旧):Kafka 早期用 ZooKeeper 存储集群元数据(Broker 列表、Topic 配置、选举信息等)
- KRaft(新):Kafka 2.8+ 引入内置的 Raft 协议替代 ZooKeeper,Kafka 4.0 已完全移除 ZooKeeper 依赖
💡 面试提示:被问到"Kafka 用 ZooKeeper 做什么"时,重点说元数据管理和 Controller 选举,并补充 KRaft 是未来趋势。
三、Kafka 整体架构
graph TB
subgraph 生产者端
App1[应用服务1]
App2[应用服务2]
end
subgraph Kafka集群
direction TB
Controller["Controller\n(集群控制器)"]
subgraph Broker1["Broker 1"]
T1P0["Topic-A / P0(Leader)"]
T2P1["Topic-B / P1(Follower)"]
end
subgraph Broker2["Broker 2"]
T1P1["Topic-A / P1(Leader)"]
T1P0R["Topic-A / P0(Follower)"]
end
subgraph Broker3["Broker 3"]
T2P0["Topic-B / P0(Leader)"]
T1P1R["Topic-A / P1(Follower)"]
end
end
subgraph 消费者端
CG1["Consumer Group 1\n(库存服务)"]
CG2["Consumer Group 2\n(短信服务)"]
end
subgraph 元数据存储
ZK[ZooKeeper / KRaft]
end
App1 -->|produce| Broker1
App2 -->|produce| Broker2
Broker1 -->|consume| CG1
Broker2 -->|consume| CG2
Broker3 -->|consume| CG2
Controller -.->|协调| Broker1
Controller -.->|协调| Broker2
Controller -.->|协调| Broker3
ZK -.->|元数据| Controller
数据流向:
- Producer → 确定目标 Partition(分区策略)→ 发送给对应 Broker(Leader)
- Broker Leader 接收消息 → 写入本地日志 → 同步给 Follower
- Consumer → 向 Broker 拉取消息 → 处理 → 提交 Offset
四、Kafka vs RabbitMQ vs RocketMQ
| 对比维度 | Kafka | RabbitMQ | RocketMQ |
|---|---|---|---|
| 定位 | 流处理平台 / 日志系统 | 传统消息队列 | 企业级消息队列 |
| 吞吐量 | 百万级/秒 | 万级/秒 | 十万级/秒 |
| 消息顺序 | 分区内有序 | 队列内有序 | 全局/分区有序 |
| 消息延迟 | 毫秒级 | 微秒级 | 毫秒级 |
| 消息积压 | 极强(日志存储) | 较弱(内存为主) | 较强 |
| 事务消息 | 支持 | 不支持 | 支持 |
| 延迟消息 | 不支持(需扩展) | 支持(插件) | 原生支持 |
| 运维复杂度 | 中(需ZooKeeper/KRaft) | 低 | 中 |
| 生态 | 超强(大数据/流处理) | 中 | 较强(阿里生态) |
| 适用场景 | 日志采集/大数据/事件流 | 业务解耦/任务队列 | 电商/金融/交易系统 |
如何选择?
大数据量 / 日志采集 / 流处理 → 选 Kafka
对消息延迟极敏感 / 复杂路由 → 选 RabbitMQ
国内电商 / 需要延迟消息 / 事务 → 选 RocketMQ
五、Kafka 在工作中的常见应用场景
mindmap
root((Kafka 应用场景))
日志收集
应用日志 → Kafka → ELK
访问日志 → Kafka → 实时分析
消息解耦
订单服务 → Kafka → 库存/短信/积分
用户注册 → Kafka → 下游多系统
流量削峰
秒杀请求 → Kafka → 排队处理
实时计算
用户行为 → Kafka → Flink → 实时推荐
数据同步
MySQL → Kafka → 多端数据同步(CDC)
六、面试高频追问
Q1:Kafka 的 Partition 数量设置多少合适?
参考答案:
没有固定答案,需要综合考虑:
- 吞吐量:目标吞吐量 / 单 Partition 吞吐量(约 10MB/s)= 最小分区数
- Consumer 数量:Partition 数 ≥ 最大 Consumer 数(否则有 Consumer 闲置)
- 文件句柄:每个 Partition 对应多个文件,过多会消耗文件描述符
- 经验值:中小规模系统 3-12 个,大规模系统按吞吐量计算
实际建议:从 6 个开始,按需扩大(可以增加 Partition,但不能减少)。
Q2:Kafka 支持哪几种消费模式?
- 点对点(Queue 模式):同一 Consumer Group 内,消息只被消费一次
- 发布订阅(Pub-Sub 模式):不同 Consumer Group 各自消费全量消息
- Kafka 通过 Consumer Group 机制同时支持上述两种模式
Q3:Kafka 的 Offset 存储在哪里?
- 旧版(0.9以前):存储在 ZooKeeper 中(性能差)
- 新版(0.9+):存储在 Kafka 内部 Topic
__consumer_offsets中 - 自定义:也可以存在 Redis / 数据库中,用于精确控制 exactly-once
Q4:为什么 Kafka 不支持主动推送,而是消费者主动拉取?
Pull 模式的优势:
- Consumer 自己控制消费速率,不会被压垮(流控友好)
- 可以批量拉取,提升吞吐量
- 便于重放历史消息
Pull 模式的缺点:
- 消息到达后有一定延迟(Consumer 需要轮询)
- Kafka 通过
fetch.min.bytes和fetch.max.wait.ms实现"长轮询"来减少空轮询
📚 下一篇
本文是 Kafka 系统学习路线 的第 1 篇


💬 文章评论 (0)