%util 100%不等于磁盘物理瓶颈,需结合await(>30ms说明排队严重)、avgqu-sz(>5表明队列满)和w/s与wkB/s比值(高IOPS低吞吐为小IO风暴)综合判断,典型根因是fsync频繁、日志同步过度或调度/挂载参数不当。

磁盘写入巨慢但 %util 显示 100%,大概率不是磁盘真坏了,而是小 IO 风暴或调度卡死——%util 高只代表“磁盘一直在忙”,不代表它物理上跑满了带宽。
iostat 看清真相:别信 %util,盯住 await 和 avgqu-sz
直接运行 iostat -x 1,重点比对这三列:
-
await> 30ms?说明请求排队严重,不是盘慢,是“堵”了 -
avgqu-sz持续 > 5?队列已满,上游发得太猛或底层响应太慢 -
w/s高但wkB/s很低(比如每秒 2000+ 次写、却只写 1MB)?典型的小文件刷盘,fsync或日志组件在疯狂落盘
如果 svctm 始终 await 却飙到 40ms,基本可排除磁盘硬件故障,问题在软件层或队列策略。
iotop 找出“写得勤但写得碎”的进程
运行 iotop -o -b -n 1(只显示正在 IO 的进程),重点关注:
- 进程状态是否为
D(不可中断睡眠)?说明它卡在内核 IO 路径里,比如等待fsync返回 -
IO>列数值高但DISK WRITE字节数不大?这是小 IO 写手的特征(如java应用打日志、rsyslog、auditd) - 命令行里有没有
sync、fsync、flush、logrotate、journalctl --rotate这类关键词?
特别注意 Java 应用:很多日志框架(Log4j2、Logback)默认 immediateFlush=true,每次 logger.info() 都触发一次 fsync,一秒钟几百次小写,%util 就被拉满了。
Linux 安全审计工具,检查 SSH 配置、开放/监听端口、防火墙规则(ufw/iptables/nftables)、失败登录尝试、sudoers 权限...
确认是不是 fsync 导致的写放大
小 IO 风暴最常见根因就是过度同步。验证方法:
- 临时关闭日志同步:
echo 'sync=false' >> /etc/rsyslog.conf(重启 rsyslog)或改 Java 日志配置里的immediateFlush - 用
strace -p PID -e trace=fsync,msync,fdatasync抓目标进程的同步调用频次 - 查
/proc/PID/stack:如果栈里反复出现__io_schedule→blk_mq_do_dispatch_sched→io_submit_one,说明它正卡在块设备队列提交环节
注意:fsync 是阻塞调用,哪怕磁盘本身很快,只要应用层调用太密,await 就会飙升,%util 也会被“假性打满”。
检查 IO 调度器和挂载选项是否匹配场景
机械盘用 cfq、SSD 用 none(或 kyber)是基础,但更关键的是挂载参数:
- 日志盘或数据库数据目录,避免用
sync或dirsync挂载选项 - 确认
/proc/sys/vm/dirty_ratio和dirty_background_ratio是否过低(比如都设成 5),会导致内核频繁唤醒pdflush强制刷脏页,把写拆成大量小 IO - SSD 上启用
noatime,nobarrier(若业务允许)能减少元数据写开销
容易被忽略的一点:容器环境里,宿主机和容器共用同一块盘时,docker logs -f 或 kubelet 日志轮转脚本可能在后台静默触发大量小写,此时 iotop 看到的 PID 可能是 containerd-shim,得顺藤摸瓜查具体容器。










