目录
[📖 前言](#📖 前言)
[1.1 问题背景](#1.1 问题背景)
[1.2 解决方案:引入Partition](#1.2 解决方案:引入Partition)
[2.1 Partition内部:严格有序](#2.1 Partition内部:严格有序)
[2.2 Partition之间:无序](#2.2 Partition之间:无序)
[2.3 设计权衡](#2.3 设计权衡)
[3.1 副本 vs 备份](#3.1 副本 vs 备份)
[3.2 Leader和Follower的职责](#3.2 Leader和Follower的职责)
[3.3 为什么只有Leader能读写?](#3.3 为什么只有Leader能读写?)
[4.1 什么是ISR?](#4.1 什么是ISR?)
[4.2 ISR的动态变化](#4.2 ISR的动态变化)
[4.3 ISR的作用](#4.3 ISR的作用)
[5.1 Controller是什么?](#5.1 Controller是什么?)
[5.2 Controller如何产生?](#5.2 Controller如何产生?)
[5.3 宕机的真实含义](#5.3 宕机的真实含义)
[6.1 核心组件](#6.1 核心组件)
[6.2 组件协同工作流程](#6.2 组件协同工作流程)
[6.3 Manager之间的关系](#6.3 Manager之间的关系)
[7.1 容易混淆的概念](#7.1 容易混淆的概念)
[7.2 关键规则](#7.2 关键规则)
[7.3 架构图解](#7.3 架构图解)
[八、ZooKeeper vs KRaft:架构演进](#八、ZooKeeper vs KRaft:架构演进)
[8.1 旧版:ZooKeeper模式](#8.1 旧版:ZooKeeper模式)
[8.2 新版:KRaft模式(Kafka ≥ 2.8)](#8.2 新版:KRaft模式(Kafka ≥ 2.8))
[8.3 KRaft架构图](#8.3 KRaft架构图)
[8.4 架构对比总结](#8.4 架构对比总结)
📖 前言
博主之前和别人在做开源的时候就曾多次接触到多种消息中间件,但Kafka的印象还是比较深刻的,最近在复习Kafka消息队列,通过结合视频教程+过去的开源实战经验发现了许多容易混淆的核心概念,于是同各位同好们分享,顺带预告一下Spring AI Alibaba会在近期继续更新。本篇回顾复习里面将深入探讨Kafka的Partition机制、副本架构、Broker内部组件,以及最重要的架构演进------从ZooKeeper模式到KRaft模式的转变。
⚠️ 版本说明: 本文对比学习了古早版Kafka(ZooKeeper模式),但会同步对比最新版Kafka(KRaft模式)的架构差异。
一、Partition概念的诞生:解决热点IO问题
1.1 问题背景
在Kafka早期设计中,如果Topic只有一个分区,会面临以下问题:
- 热点IO:所有消息写入同一个磁盘文件,单块磁盘的IOPS(每秒读写次数)有限制
- 无法水平扩展:受限于单机性能,只能通过升级硬件(垂直扩展)提升性能
- 单点故障:这个分区所在的Broker挂了,整个Topic就不可用
1.2 解决方案:引入Partition
Kafka通过引入Partition(分区)概念,将Topic拆分为多个物理分区:
Topic (逻辑概念)
↓
Partition-0, Partition-1, Partition-2 (物理分割)
↓
每个Partition是独立的.log文件
↓
分布在不同Broker上,实现并行IO
核心思想: 从"单车道"变成"多车道",总吞吐量 = 所有Partition吞吐量之和。
二、Partition的有序性------局部有序,非全局有序
2.1 Partition内部:严格有序
✅ 同一个Partition内的消息是严格有序的
原因:Kafka的Partition采用追加日志设计,只能尾部追加,消息按到达顺序写入,Consumer也按offset顺序读取。
2.2 Partition之间:无序
❌ 不同Partition之间的消息没有顺序关系
示例:
生产者发送:Msg1 → Msg2 → Msg3 → Msg4
实际分布:
partition-0: Msg1, Msg4
partition-1: Msg2
partition-2: Msg3
消费者读取时可能是:
Msg1 → Msg4 → Msg2 → Msg3 ❌ 无序!
2.3 设计权衡
Kafka选择了牺牲全局有序性,换取高吞吐量。如果需要保证业务有序性,可以将同一业务的消息路由到同一个Partition。
三、副本机制------Leader独占读写
3.1 副本 vs 备份
| 特性 | 备份(传统) | 副本(Kafka) |
|---|---|---|
| 角色 | 冷数据,只存储不服务 | 热数据,同时提供服务 |
| 作用 | 灾难恢复 | 高可用 + 负载均衡 |
| 访问 | 主节点故障后才启用 | 所有副本都可被读取 |
| 设计理念 | 被动存储 | 主动服务 |
3.2 Leader和Follower的职责
关键原则:
- ✅ Leader:唯一具备数据读写能力的副本
- ✅ Follower :只从Leader同步数据,不接受客户端的读写请求
数据流向:
生产者写入:
Producer → Leader (写请求)
↓
Follower (被动同步)
消费者读取:
Consumer → Leader (读请求)
↓
Follower (默认不读)
3.3 为什么只有Leader能读写?
保证数据一致性 :所有写操作经过Leader,避免分布式冲突
简化同步逻辑 :单向同步(Leader → Follower),无需复杂的分布式事务
性能优化:Leader统一处理请求,避免协调开销
四、ISR机制------同步副本集合
4.1 什么是ISR?
ISR = In-Sync Replicas(同步副本集合)
ISR中包含所有与Leader保持同步的副本。只有ISR中的副本才能竞选为新Leader。
4.2 ISR的动态变化
初始状态:
Leader: Broker-1 (offset=100)
Broker-2: offset=100
Broker-3: offset=100
ISR: [Broker-1, Broker-2, Broker-3]
Broker-2网络拥塞,同步延迟:
Leader: Broker-1 (offset=200)
Broker-2: offset=100 ← 延迟100条消息!
Broker-3: offset=200
检查ISR条件:
Broker-2的延迟超过 replica.lag.time.max.ms
→ 从ISR中移除Broker-2
新的ISR: [Broker-1, Broker-3]
4.3 ISR的作用
保证数据不丢失 :选举Leader时只在ISR中选择,确保新Leader的数据是最新的
动态管理 :延迟大的副本会被自动踢出
快速故障恢复:无需手动干预,自动调整ISR
五、Controller选举与分布式协调
5.1 Controller是什么?
Controller是Kafka集群的"中央协调器",负责:
- 管理集群元数据
- 监控Broker健康状态
- 协调Partition Leader选举
- 分配Partition给Broker
5.2 Controller如何产生?
不是人为指定! 而是通过竞争产生:
旧版(ZooKeeper模式):
多个Broker竞争创建ZooKeeper临时节点 /controller
谁创建成功谁就是Controller
新版(KRaft模式):
Controller Quorum通过Raft协议投票选举Leader
宕机的真实含义(补充概念)
在分布式系统中,"宕机"不等于机器停机,还包括:
- 网络拥塞、连接超时
- GC停顿过长
- 磁盘IO满载、CPU过载
Kafka的判断标准: 如果超过 session.timeout.ms 没收到心跳,认为该Broker"宕机"。
六、Broker内部架构------组件协同
6.1 核心组件
关键组件:
- SocketServer:网络层,建立长连接,处理客户端连接
- ReplicaManager:管理副本(Leader/Follower)
- LogManager:管理日志文件(.log文件的读写)
- PartitionManager:管理分区
- NetworkClient:Broker间通信(Follower从Leader拉取数据)
6.2 组件协同工作流程
场景:Producer发送一条消息
第1步:建立连接
Producer → Broker (TCP长连接)
第2步:发送写入请求
Producer → Broker (ProduceRequest)
第3步:SocketServer接收
SocketServer.Acceptor接收 → 分配给Processor处理
第4步:请求分发
RequestChannel分析请求 → 分发给ReplicaManager
第5步:ReplicaManager处理
"我是Leader" → 调用LogManager写入文件
第6步:LogManager写入
写入.log文件 → offset=100 → 返回成功
第7步:返回响应
Broker → Producer (ProduceResponse, offset=100)
6.3 Manager之间的关系
不是上下级关系,而是平行的不同部门!
ReplicaManager ←调用→ LogManager
"我需要写入" "我来写文件"
通过互相调用或事件协调,而非命令式管理
七、Partition、Replica、Broker的关系
7.1 容易混淆的概念
- Partition(分区):Topic的逻辑/物理分割,每个Partition是独立的.log文件
- Replica(副本):每个Partition的备份,分布在不同Broker上
- Broker(服务器):Kafka集群中的节点
7.2 关键规则
✅ 副本数量不能超过Broker数量
错误:3个Broker,设置4个副本(放不下!)
正确:3个Broker,设置3个副本
✅ 一个Broker上可以有多个Partition
实际生产环境:
Broker-1上可能有几十甚至上百个Partition
既是某些Partition的Leader,又是其他Partition的Follower
7.3 架构图解
1 Broker = 1 Partition的简化模型:
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Broker-1 │ │ Broker-2 │ │ Broker-3 │
│ P-0(Ldr) │ │ P-1(Ldr) │ │ P-2(Ldr) │
│ P-1(Flw) │ │ P-2(Flw) │ │ P-0(Flw) │
└──────────┘ └──────────┘ └──────────┘
实际生产环境(1 Broker = 多个Partition):
┌──────────────────┐ ┌──────────────────┐
│ Broker-1 │ │ Broker-2 │
│ ┌──────────────┐ │ │ ┌──────────────┐ │
│ │ Topic-A P-0 │ │ │ │ Topic-A P-1 │ │
│ │ (Leader) │ │ │ │ (Leader) │ │
│ └──────────────┘ │ │ └──────────────┘ │
│ ┌──────────────┐ │ │ ┌──────────────┐ │
│ │ Topic-A P-3 │ │ │ │ Topic-A P-4 │ │
│ │ (Follower) │ │ │ │ (Follower) │ │
│ └──────────────┘ │ │ └──────────────┘ │
│ ... │ │ ... │
└──────────────────┘ └──────────────────┘
八、ZooKeeper vs KRaft------架构演进
8.1 旧版:ZooKeeper模式
ZooKeeper的两种节点类型:
- 持久化节点:创建后一直存在,用于存储Topic配置等元数据
- 临时节点:绑定会话,会话结束自动删除,用于Controller选举和Broker存活检测
Controller选举流程:
Broker-1, Broker-2, Broker-3启动
↓
竞争创建 /controller 临时节点
↓
Broker-1创建成功 → 成为Controller
↓
Broker-1宕机 → 临时节点删除
↓
触发重新选举
8.2 新版:KRaft模式(Kafka ≥ 2.8)
核心思想:Kafka自己管理元数据,不再依赖外部系统
功能对照表:
| ZooKeeper功能 | KRaft替代方案 | 实现机制 |
|---|---|---|
| 持久化节点 | Metadata Log记录 | Raft协议复制 |
| 临时节点 | Broker注册+心跳 | 心跳超时自动移除 |
| Controller选举 | Raft Leader选举 | Quorum Controller投票 |
| 元数据存储 | __cluster_metadata Topic | 内部Topic |
8.3 KRaft架构图
┌─────────────────────────────────────────┐
│ Controller Quorum (Raft协议) │
│ ┌──────────┐ ┌──────────┐ ┌────────┐ │
│ │Broker-1 │ │Broker-2 │ │Broker-3│ │
│ │Controller│ │Controller│ │Control │ │
│ │(Leader) │ │(Follower)│ │Follower│ │
│ └────┬─────┘ └────┬─────┘ └───┬────┘ │
│ │Raft │Raft │ │
│ └────────────┴────────────┘ │
│ ↓ │
│ __cluster_metadata │
│ (内部Topic,存元数据) │
└─────────────────────────────────────────┘
8.4 架构对比总结
| 特性 | ZooKeeper模式 | KRaft模式 |
|---|---|---|
| 外部依赖 | 需要ZooKeeper集群 | 无需外部依赖 |
| 元数据存储 | ZooKeeper节点 | Metadata Log |
| Controller选举 | 竞争临时节点 | Raft投票 |
| Controller数量 | 1个(单点) | Quorum(多个) |
| 运维复杂度 | 高(两套系统) | 低(单一系统) |
总结🎯
Kafka通过分区(Partition) 机制将数据流分散存储,实现水平扩展与高吞吐;采用Leader-Follower副本架构 ,由Leader统一处理读写以保证一致性,Follower则同步备份提供容错;通过ISR(同步副本集合) 动态管理健康副本,确保故障切换时数据不丢失;其协调核心Controller(旧版依赖ZooKeeper,新版基于KRaft实现自管理)负责元数据与选举协调。