Kafka 基础概念¶
1. 引入:它解决了什么问题?¶
问题背景:没有消息队列时,服务间通信是同步调用,存在三大痛点:
flowchart LR
subgraph 同步调用的问题
A[订单服务] -->|同步调用| B[库存服务]
A -->|同步调用| C[积分服务]
A -->|同步调用| D[通知服务]
B -->|任一失败| E[整体失败]
C --> E
D --> E
end
| 痛点 | 具体表现 | Kafka 的解决方案 |
|---|---|---|
| 强耦合 | 订单服务必须知道所有下游服务的接口 | 生产者只写 Topic,不关心消费者 |
| 性能差 | 需要等待所有下游服务响应才能返回 | 生产者写完即返回,异步处理 |
| 可用性低 | 任一下游服务宕机,整个链路失败 | 消费者宕机后恢复可继续消费 |
| 流量峰值 | 瞬时高峰直接打到下游服务 | Kafka 作为缓冲层,消费者按能力消费 |
不了解 Kafka 会导致的线上问题:
- 消息丢失:acks=1 时 Leader 宕机,消息未同步到副本
- 消息重复:消费者处理成功但提交 offset 前崩溃,重启后重新消费
- 消息积压:消费者处理速度跟不上生产速度,Lag 持续增大
- 顺序错乱:多分区消费,同一订单的消息被不同消费者处理
2. 类比:用生活模型建立直觉¶
把 Kafka 类比为快递分拣中心:
| Kafka 概念 | 生活类比 | 映射关系 |
|---|---|---|
| Topic | 快递类别(电子产品/食品/服装) | 消息的逻辑分类 |
| Partition | 同类快递的多条传送带 | 并行处理的基本单位 |
| Producer | 寄件人 | 发送消息的服务 |
| Consumer | 收件人 | 消费消息的服务 |
| Consumer Group | 同一公司的多个收件人 | 组内分工,每条传送带只有一人负责 |
| Offset | 快递单号 | 消息在分区中的位置,消费者用它记录进度 |
| Broker | 分拣中心的仓库 | 存储分区数据的服务器 |
关键直觉:Kafka 是"异步邮局",寄件人(Producer)把信投进邮箱(Topic)就走,不等收件人(Consumer)签收。邮局(Broker)负责保管,收件人按自己的节奏取信。
3. 核心概念¶
3.1 概念全景图¶
flowchart TB
subgraph Kafka 核心概念
Topic["Topic(主题)\n消息的逻辑分类\n如:order-created"]
Partition["Partition(分区)\nTopic 的物理分片\n并行度的基本单位"]
Replica["Replica(副本)\n分区的备份\n保证高可用"]
Offset["Offset(偏移量)\n消息在分区中的位置\n消费者用它记录进度"]
ConsumerGroup["Consumer Group(消费者组)\n同组消费者共同消费一个 Topic\n每个分区只被组内一个消费者消费"]
Broker["Broker(节点)\nKafka 服务器实例\n存储分区数据"]
end
Topic --> Partition
Partition --> Replica
Partition --> Offset
Topic --> ConsumerGroup
Broker --> Partition
3.2 Topic 与 Partition 的关系¶
flowchart LR
subgraph "Topic: order-created(3个分区)"
P0["Partition 0\nLeader: Broker1\nFollower: Broker2"]
P1["Partition 1\nLeader: Broker2\nFollower: Broker3"]
P2["Partition 2\nLeader: Broker3\nFollower: Broker1"]
end
subgraph 消费者组 A
C1["Consumer 1\n消费 P0"]
C2["Consumer 2\n消费 P1"]
C3["Consumer 3\n消费 P2"]
end
P0 --> C1
P1 --> C2
P2 --> C3
关键规则: - 同一消费者组内,一个分区只能被一个消费者消费(保证顺序性) - 消费者数量 > 分区数时,多余的消费者空闲等待(浪费资源,分区数应 ≥ 消费者数) - 消费者数量 < 分区数时,一个消费者会消费多个分区
3.3 Offset 机制¶
Partition 0 的消息序列:
┌─────┬─────┬─────┬─────┬─────┬─────┐
│ msg │ msg │ msg │ msg │ msg │ msg │
│ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │
└─────┴─────┴─────┴─────┴─────┴─────┘
↑
Consumer A 当前消费到 offset=3
下次从 offset=4 开始消费
Offset 存储位置:Kafka 0.9+ 存储在内部 Topic __consumer_offsets 中(之前存 ZooKeeper)
为什么从 ZooKeeper 迁移到内部 Topic:ZooKeeper 不适合高频写入(每次消费都要更新 offset),而 Kafka 本身就是高吞吐的存储系统,用内部 Topic 存储 offset 性能更好,也减少了对 ZooKeeper 的依赖。