作者介绍:简历上没有一个精通的运维工程师。请点击上方的蓝色《运维小路》关注我,下面的思维导图也是预计更新的内容和当前进度(不定时更新)。
我们上一章介绍了中间件:Zookeeper,本章将介绍另外一个中间件:Kafka。目前这2个中间件都是基于JAVA语言的。
在面试的时关于Kafa问题的时候,我们经常会问一个问题就是Kafka为什么这么快,这里最主要有两个因素:顺序读写和零拷贝(Zero-Copy),今天我们先来介绍顺序读写。
顺序读写:磁盘的高效利用
1. 顺序读写的本质优势
-
磁盘的物理特性:
-
机械硬盘(HDD):磁头寻道(Seek Time)和旋转延迟(Rotational Latency)是随机 I/O 的主要瓶颈。顺序读写时,磁头只需按固定方向移动,避免了频繁寻道,吞吐量可接近磁盘的理论最大值(例如 100 MB/s 以上)。
-
固态硬盘(SSD):虽然 SSD 的随机 I/O 性能远高于 HDD(主要是SSD没有机械磁头的旋转动作),但顺序读写仍比随机快 2-3 倍。SSD 的擦除操作以块(Block,通常 128KB~4MB)为单位,顺序写入能减少块内碎片,延长寿命。
-
#下面测试数据来源元一台阿里云的服务器 ,使用fio工具测试
#顺序读写
seq-read: (groupid=0, jobs=1): err= 0: pid=3705: Sun May 18 23:30:21 2025
read: IOPS=1365, BW=1365MiB/s (1432MB/s)(1024MiB/750msec)
seq-write: (groupid=0, jobs=1): err= 0: pid=3704: Sun May 18 23:30:21 2025
write: IOPS=112, BW=113MiB/s (118MB/s)(1024MiB/9073msec)
#随机读写
rand-write: (groupid=0, jobs=1): err= 0: pid=3706: Sun May 18 23:30:21 2025
write: IOPS=855, BW=3424KiB/s (3506kB/s)(100MiB/30001msec)
rand-read: (groupid=0, jobs=1): err= 0: pid=3707: Sun May 18 23:30:21 2025
read: IOPS=1047, BW=4189KiB/s (4290kB/s)(123MiB/30001msec)
-
操作系统优化:
-
预读(Read-ahead):当检测到顺序读取时,操作系统会提前加载后续数据到页缓存(Page Cache),减少后续读请求的延迟。
-
延迟写(Write-behind):操作系统将多个小写入合并为一个大块写入磁盘,减少 I/O 次数(例如合并 10 次 1KB 写入为一次 10KB 写入)。
-
2. Kafka 如何实现严格的顺序读写?
-
日志结构存储(Log-Structured Storage):
-
只追加(Append-Only)写入:所有消息按到达顺序追加到分区(Partition)的日志文件中,写入操作天然顺序。
-
不可变性(Immutable):已写入的消息不可修改或删除,避免了随机更新或覆盖操作。
-
-
分段(Segment)机制:
-
按大小或时间切分日志:每个分区的日志被拆分为多个固定大小的 Segment 文件(例如 1GB)。当前活跃的 Segment(如
00000000000000000.log
)仅用于写入,旧 Segment 只读。 -
删除策略:通过定期删除或压缩旧 Segment 文件(而非修改内容)清理数据,避免破坏顺序性。
-
-
稀疏索引(Sparse Index):
-
偏移量索引(
.index
文件):记录消息偏移量到物理位置的映射,索引条目间隔较大(例如每隔 1KB 数据建一个索引点)。 -
时间戳索引(
.timeindex
文件):记录时间戳到偏移量的映射,支持按时间范围快速定位。 -
索引的作用:消费者读取时,先通过索引定位到目标数据的大致位置,再顺序扫描少量数据,避免全量扫描。
-
运维小路
一个不会开发的运维!一个要学开发的运维!一个学不会开发的运维!欢迎大家骚扰的运维!
关注微信公众号《运维小路》获取更多内容。