4、磁盘I/O性能分析:磁盘工作原理、I/O调度器、iostat与iotop实战、IOPS与吞吐量

磁盘I/O,说白了就是整个系统最慢的那一环。我见过太多应用,CPU和内存都闲得发慌,结果业务卡得不行,一查全是磁盘在拖后腿。今天咱们就把磁盘I/O这块彻底聊透。

4.1 磁盘工作原理:机械盘与SSD的差异

先说说机械硬盘(HDD)。它的核心结构其实很简单:盘片、磁头、马达。读数据时,磁头要移动到对应磁道(寻道时间),然后等盘片转到目标扇区(旋转延迟)。这两个动作,就是机械盘最慢的地方。

我在项目中遇到过一台数据库服务器,每秒查询量一上来,磁盘利用率直接飙到100%。后来发现是机械盘的随机读写性能太差,寻道时间占了大部分开销。换成SSD后,问题立刻缓解。

SSD就不一样了。它没有机械部件,靠闪存颗粒存储数据。随机读写性能比机械盘高出一个数量级。但SSD也有短板——写放大和寿命问题。频繁的小块写入,会让SSD的寿命快速消耗。

核心差异总结:
  • HDD:顺序读写快,随机读写慢(寻道+旋转延迟)
  • SSD:随机读写快,但存在写放大和磨损均衡问题
  • HDD适合大文件顺序读写,SSD适合高并发随机I/O

4.2 I/O调度器:内核如何管理磁盘请求

Linux内核里有个东西叫I/O调度器。它的任务很简单:把一堆乱糟糟的I/O请求排好队,尽量让磁盘干活更高效。

常用的调度器有几种:

  • CFQ(完全公平队列):每个进程一个队列,公平分配时间片。适合桌面环境,但服务器场景下延迟偏高。
  • Deadline:给每个请求设一个截止时间,优先处理快超时的请求。能有效避免某个请求被饿死。
  • NOOP:什么都不做,直接按先进先出处理。适合SSD,因为SSD不需要寻道优化。
  • Kyber:基于延迟的调度器,自动调整队列深度,适合NVMe SSD。

我个人习惯在数据库服务器上用Deadline。为什么?因为数据库对延迟敏感,Deadline能保证写请求不会等太久。我曾经调过一台MySQL服务器,从CFQ换成Deadline后,写延迟直接降了30%。

小技巧:查看当前调度器用 cat /sys/block/sda/queue/scheduler,临时切换用 echo deadline > /sys/block/sda/queue/scheduler。永久修改要改grub参数。

4.3 iostat实战:读懂磁盘性能指标

iostat是我排查磁盘问题时的第一把刀。它的输出信息很丰富,但很多人只盯着%util看,其实不够。

先看一个典型输出:

$ iostat -x 1 5
Device  r/s   w/s   rkB/s   wkB/s  await  svctm  %util
sda     120   80   4800    3200   12.5   4.2    85.0

几个关键指标:

  • r/s, w/s:每秒读写请求数。这个值直接反映I/O并发度。
  • rkB/s, wkB/s:每秒读写数据量。结合r/s可以算出平均I/O大小。
  • await:I/O请求的平均等待时间(包括排队和服务时间)。这个值超过20ms就要警惕了。
  • svctm:I/O请求的实际服务时间。机械盘一般在5-10ms,SSD在0.1-1ms。
  • %util:磁盘忙闲比例。但要注意,%util到100%不代表磁盘真的满了,可能是队列深度不够。

我记得有一次帮客户排查,%util只有60%,但业务已经卡得不行。后来发现是队列深度太小,请求都在排队。调大队列深度后,%util上去了,延迟反而降了。

避坑指南:我曾经被%util骗过好几次。它只能反映磁盘是否在干活,不能反映性能瓶颈。真正要看的是await和svctm的差值。如果await远大于svctm,说明排队严重,磁盘确实忙不过来了。

4.4 iotop实战:定位哪个进程在吃I/O

iostat能告诉你磁盘忙不忙,但谁在搞事?这时候就要用iotop了。

iotop的原理很简单:它监控每个进程的I/O读写速率,然后按大小排序。用法也很直接:

$ iotop -oP
Total DISK READ : 0.00 B/s | Total DISK WRITE : 15.00 M/s
  PID  PRIO  DISK READ  DISK WRITE  COMMAND
 1234  be/4  0.00 B/s   12.00 M/s   mysqld
 5678  be/4  0.00 B/s    3.00 M/s   java

参数说明:

  • -o:只显示有I/O活动的进程
  • -P:只显示进程,不显示线程
  • -a:显示累计I/O量

实战中,我经常这样用:先跑iostat发现磁盘压力大,然后立刻开iotop看是哪个进程在写。有一次发现是日志收集进程在疯狂写磁盘,把数据库的I/O都抢走了。调整日志级别后,问题解决。

提示:iotop需要root权限。如果不想装iotop,也可以用pidstat -d 1替代,效果类似。

4.5 IOPS与吞吐量:两个容易混淆的概念

IOPS和吞吐量,很多人混着用。其实它们描述的是两个维度。

IOPS:每秒能处理多少个I/O请求。它衡量的是并发处理能力。随机读写场景下,IOPS是关键指标。

吞吐量:每秒能传输多少数据。它衡量的是带宽。顺序读写场景下,吞吐量是关键指标。

举个例子:机械盘的IOPS大概在100-200,但顺序吞吐量能到200MB/s。SSD的IOPS能到几万甚至几十万,但吞吐量可能只有500MB/s。你想想看,如果业务是大量小文件随机读写,IOPS就是瓶颈;如果是大文件顺序拷贝,吞吐量才是关键。

我在项目中遇到过一台文件服务器,用户抱怨上传慢。一查,IOPS只有80,但吞吐量还有富余。后来发现是文件碎片太多,导致随机读写性能下降。整理碎片后,IOPS翻了一倍。

场景 关注指标 典型值(HDD) 典型值(SSD)
数据库OLTP IOPS 100-200 10,000-100,000
视频流媒体 吞吐量 100-200 MB/s 300-500 MB/s
日志写入 IOPS + 吞吐量 50-100 IOPS 5,000-20,000 IOPS
一句话总结:IOPS看并发,吞吐量看带宽。选型时先搞清楚业务是随机读写还是顺序读写,再决定关注哪个指标。

4.6 知识体系图:磁盘I/O分析全景

下面这张图把磁盘I/O分析的核心逻辑串起来了。从硬件原理到调度策略,再到监控工具和关键指标,一条线走通。

磁盘I/O性能分析知识体系 磁盘硬件 HDD vs SSD I/O调度器 CFQ/Deadline/NOOP 监控工具 iostat / iotop 关键指标 IOPS / 吞吐量 await / svctm / %util 性能瓶颈定位 排队延迟 vs 服务延迟 进程级I/O排查 优化手段 调度器调优 队列深度调整 实战流程:iostat发现瓶颈 → iotop定位进程 → 分析指标 → 优化调度 核心:先懂原理,再会工具,最后看指标

嗯,到这里磁盘I/O这块就聊得差不多了。记住一句话:磁盘性能问题,80%都能通过iostat+iotop的组合拳定位出来。剩下的20%,需要结合业务逻辑和文件系统特性去深挖。


公众号:蓝海资料掘金营,微信deep3321