IO wait 爆高怎么办:iostat+iotop 排查磁盘瓶颈

CPU 很闲但网站卡成 PPT?八成是磁盘 IO 瓶颈。小够教你用 iostat 看 %util 和 await、iotop 揪出吃 IO 的进程,从症状到根治一条龙。

我是小够。有种卡很气人:top 一看 CPU 才用了 20%,内存也够,但网站慢得像 PPT,SSH 敲命令都卡顿。这种八成是磁盘 IO 瓶颈——CPU 在等磁盘,干等着啥也干不了。

先确认:是不是 IO 的问题

top

看 %wa(iowait)这一项。如果长期超过 20-30%,基本可以断定是 IO 瓶颈。CPU 闲、iowait 高,就是"有力使不出"的典型症状。

iostat:看磁盘忙不忙

# 每 2 秒刷新一次
iostat -x 2

看这几个指标:

  • %util:磁盘忙碌程度。长期接近 100%,磁盘已经顶满了
  • await:平均每次 IO 等待时间。SSD/NVMe 正常应该是个位数毫秒,几十毫秒以上就是有问题
  • r/s、w/s:每秒读写次数,突然暴涨说明有进程在狂写

%util 100% + await 几百毫秒,磁盘瓶颈实锤。

iotop:揪出元凶进程

sudo iotop -oP

-o 只显示正在做 IO 的进程,-P 按进程不按线程。直接看到谁在狂读写。

小够见过的常见元凶:

  1. 备份任务:凌晨备份打 tar,几十 GB 的读写,正常现象,错峰就行
  2. 日志狂写:某个应用 debug 日志全开,每秒写几 MB
  3. 数据库:慢查询、缺索引,全表扫描把磁盘打满
  4. swap 疯狂换页:内存不够,系统在内存和磁盘之间倒腾,IO 直接爆炸——先解决内存问题
  5. 被入侵:陌生进程狂写盘,先断网查,别犹豫

缓解:先止血

  • 备份/定时任务错峰,别和业务高峰撞车
  • 日志级别调低,debug 只在排查时开
  • 数据库加索引、开慢查询日志找元凶
  • 加内存(如果是 swap 引起的 IO 问题)

根治:看配置够不够

如果业务正常、没有异常进程,但 %util 长期 80% 以上,说明磁盘性能真的不够了:

  • 看商家给的是什么盘:SSD 和 NVMe 差不少,fio 简单测一下 4k 随机读写心里有数
  • 数据库类应用对 IO 最敏感,选 VPS 时磁盘性能权重放高点
  • 实在不行:读写分离、加缓存(Redis)、上更好的盘

小够的建议

IO 问题有个特点:平时没事,忙时爆炸。所以别只在出问题时看,平时就装个监控把 %util 和 await 画成曲线,趋势一抬头就提前处理。记住排查顺序:top 看 iowait → iostat 确认 → iotop 找进程 → 先止血再根治。

fio:简单测一下盘的底子

怀疑盘不行,先测个底:

# 4k 随机读,模拟数据库负载
fio --name=test --rw=randread --bs=4k --size=1G --runtime=60 --iodepth=32

看 iops 和 bw。家用 SSD 4k 随机读轻松几万 IOPS,VPS 上差一些正常,但如果只有几百,那这盘是真的不行——要么换商家,要么认命。

YABS 跑分里的 fio 测试也是这个原理,之前讲 YABS 解读时提过。

iotop 进阶用法

sudo iotop -oPa

-a 显示累计 IO 量,一眼看出"从开机到现在谁读写最多"。有些进程平时不显眼,累计起来吓人一跳。

数据库 IO 优化

数据库是 IO 大户,几个立竿见影的:

  1. 加索引:慢查询日志开起来(slow_query_log),把全表扫描的 SQL 找出来加索引,IO 直接降一个数量级
  2. 调大 buffer:innodb_buffer_pool_size 给够,热数据放内存里,少读盘
  3. 分开存放:数据和日志放不同磁盘(有条件的话),读写不打架

备份错峰实战

备份是 IO 洪峰,但它是可预测的:

  • 凌晨 2-4 点跑,避开业务时间
  • ionice 给备份进程降 IO 优先级:
ionice -c3 tar -czf backup.tar.gz /var/www

-c3 是 idle 级别:有空闲 IO 才用,业务优先。备份慢点没关系,别影响业务。

  • rsync 加 --bwlimit,网络和磁盘双限速

常见问题

Q:iowait 高,但 iotop 看不到大户? A:可能是内核线程(如 kswapd 换页、jbd2 文件系统日志)在忙。用 iostat -x 看是哪块盘,再结合 dmesg 看有没有磁盘报错。磁盘硬件故障也会表现为 iowait 爆高。

Q:SSD 的盘也会 IO 瓶颈吗? A:会。超售严重的机器,几十台 VPS 抢一块盘,SSD 也顶不住。fio 测出来的数字不会骗人,长期不达标就换商家。

Q:加内存能缓解 IO 问题吗? A:很多时候能。文件系统缓存(page cache)就在内存里,内存越大,读盘越少。1G 内存跑数据库又卡又慢,加到 2G 可能直接解决问题。

长期监控 IO

# sar 记录历史(sysstat 包)
sudo apt install sysstat
# /etc/default/sysstat 里把 ENABLED 改成 true

之后 sar -d 看历史磁盘数据,“上周三凌晨 IO 爆了"这种,回头能查到。排查 IO 问题,历史数据比现场抓更重要,因为 IO 毛刺往往几分钟就过去了。

读写分离的思路

数据库读多写少?读写分离:

  • 写走主库,读走备库(或只读副本)
  • 主库的 IO 压力直接减半

小业务用不上,但这是 IO 瓶颈的终极解法之一。先知道有这条路,真到那天不抓瞎。

选 VPS 时看 IO

买 VPS 时 IO 性能怎么看:

  1. YABS 跑分:看 4k 随机读写的 IOPS,别只看顺序读写
  2. 问客服:超售严不严重(一般不会说实话,但可以问)
  3. 实测:买回来先 fio 跑一遍,不达标 7 天内退款(看商家退款政策)

便宜 VPS 的 IO 普遍一般,跑博客够用,跑数据库要掂量。小够的建议:数据库类应用,磁盘性能的权重和 CPU 一样高。

常见问题

Q:iowait 高,但 %util 不高? A:那可能是网络文件系统(NFS)在等,或者进程在等锁,不一定是本地盘。用 iostat -x 看具体哪块设备,再看 dmesg 有没有报错。

Q:SSD 需要碎片整理吗? A:不需要,那是机械盘时代的事。SSD 乱擦除,碎片整理反而折寿。TRIM 开着就行:systemctl status fstrim.timer。

Q:怎么知道是邻居在抢 IO? A:iostat 看到 %util 100%,但 iotop 里自己进程的 IO 很小——那就是邻居(同一宿主机的其他 VPS)在抢。这是超售的典型症状,换商家吧。