磁盘队列深度过长(avgqu-sz持续偏高)表明i/o请求在块层积压,导致进程d状态、系统卡顿但cpu/内存正常;需分三步排查:确认指标异常(avgqu-sz与await同步升高)、定位源头进程(iotop/pidstat)、检查底层限制(设备队列、调度器、挂载参数),并排除硬件故障。

磁盘队列深度过长(即 avgqu-sz 持续偏高)意味着 I/O 请求在内核块层大量积压,进程频繁陷入不可中断睡眠(D 状态),系统表现为整体卡顿、SSH 响应迟缓、df/ls 无响应,但 CPU 和内存使用率可能看起来正常。这不是磁盘空间满,而是“请求发得太快,设备处理不过来”。排查要分三步:确认是否真高、揪出源头进程、检查底层限制。
看 avgqu-sz 和 await 是否同步异常
运行 iostat -x 1 持续观察,重点关注两个联动指标:
-
avgqu-sz:平均队列长度。HDD 超过 2 就需警惕;SATA SSD 超过 8 表示压力明显;NVMe 长期高于 32 且
%util未达 90%,说明上层并发远超设备能力 -
await:平均等待毫秒数。若
avgqu-sz高的同时await也飙升(如 >100ms),基本可断定是真实瓶颈;若await仅几毫秒,可能是短时突发,不构成持续延迟 - 拆开看
r_await和w_await:写等待显著更高,优先查日志刷盘、sync写入或文件系统 journal 模式(如 ext4 的data=journal)
揪出正在狂发 I/O 请求的进程
top 里看到的 D 状态进程是受害者,不是源头。要用能直接抓 I/O 行为的工具:
- 用
sudo iotop -oP -d 1:只显示实际有 I/O 的进程,按吞吐排序,一眼锁定高 IO 的 PID - 用
pidstat -d 1:输出稳定,带kB_rd/s、kB_wr/s,还能看到pgpgin/pgpgout——若换页量大,说明内存不足间接引发大量 swap I/O - 容器环境要关联服务名:对可疑 PID 执行
cat /proc/<pid>/cgroup | grep docker | awk -F'/' '{print $NF}' | cut -c1-12</pid>,快速定位所属容器
查设备队列、调度器与挂载参数这三道关卡
队列深度受硬件、内核和文件系统三层硬约束,光杀进程治标不治本:
-
设备队列大小:执行
cat /sys/block/sda/queue/nr_requests(把sda换成实际盘符)。常见值为 128 或 256;若远低于磁盘能力(如 NVMe 支持 1024),可适当调高 -
I/O 调度器:运行
cat /sys/block/sda/queue/scheduler。HDD 推荐deadline;SSD/NVMe 推荐none(NVMe)或mq-deadline;cfq已淘汰,易堆积 -
挂载参数:执行
mount | grep sda,重点检查:
–data=journal:ext4 下双倍 I/O,改用data=ordered或data=writeback
–barrier=1、commit=5:加重同步负担,高负载场景可考虑barrier=0(需确保有 UPS 或断电保护)
补充验证:排除硬件与存储后端问题
如果上述都正常,但 await 仍长期偏高,就得往更底层查:
- 查磁盘健康:
sudo smartctl -a /dev/sda,关注Reallocated_Sector_Ct、Current_Pending_Sector、UDMA_CRC_Error_Count——非零且上升,说明磁盘快坏了,重试会拖垮队列 - 查内核报错:
dmesg -T | tail -30,找Buffer I/O error、end_request: I/O error、ata timeout类提示,这是硬件失败的铁证 - 检查文件系统是否只读:
mount | grep "$(df . | tail -1 | awk '{print $1}')",若含ro,说明因错误自动降级,所有写操作都会阻塞











