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 按进程不按线程。直接看到谁在狂读写。
小够见过的常见元凶:
- 备份任务:凌晨备份打 tar,几十 GB 的读写,正常现象,错峰就行
- 日志狂写:某个应用 debug 日志全开,每秒写几 MB
- 数据库:慢查询、缺索引,全表扫描把磁盘打满
- swap 疯狂换页:内存不够,系统在内存和磁盘之间倒腾,IO 直接爆炸——先解决内存问题
- 被入侵:陌生进程狂写盘,先断网查,别犹豫
缓解:先止血
- 备份/定时任务错峰,别和业务高峰撞车
- 日志级别调低,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 大户,几个立竿见影的:
- 加索引:慢查询日志开起来(
slow_query_log),把全表扫描的 SQL 找出来加索引,IO 直接降一个数量级 - 调大 buffer:
innodb_buffer_pool_size给够,热数据放内存里,少读盘 - 分开存放:数据和日志放不同磁盘(有条件的话),读写不打架
备份错峰实战
备份是 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 性能怎么看:
- YABS 跑分:看 4k 随机读写的 IOPS,别只看顺序读写
- 问客服:超售严不严重(一般不会说实话,但可以问)
- 实测:买回来先
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)在抢。这是超售的典型症状,换商家吧。