毛刺是随机读写场景下page cache回收或刷盘压力导致的io延迟突增现象,表现为业务响应时延骤升、load飙升、i/o吞吐异常,根源在于内核缓存管理机制与高并发小数据块写入不匹配。

request_time 毛刺本身不直接等于磁盘缓存 IO 延迟,但它是一个关键线索——尤其当毛刺集中在特定时间点、与应用行为(如批量写入、日志刷盘、定时 sync)同步出现时,往往指向内核页缓存(page cache)管理引发的延迟突增。
先确认 request_time 是否真由磁盘 IO 引起
request_time 是 Web 服务器(如 Nginx)记录的整个请求处理耗时,包含网络、CPU、锁、内存分配、文件系统调用等全部环节。不能默认归因为磁盘。
验证步骤:
- 对比同一时段的 %wa(iowait):用
top或vmstat 1观察,若 %wa 显著升高(如 >20%),且与 request_time 毛刺重合,说明 CPU 确实在等 I/O - 检查 await 是否同步飙升:运行
iostat -dx 1,关注目标设备的await、r_await、w_await。若毛刺期间 await >1ms(SSD)或 >10ms(HDD),且%util未达 100%,说明不是设备瓶颈,而是上层排队或缓存刷盘阻塞 - 看 avgqu-sz:若该值长期 >1 且随毛刺跳变,说明 I/O 请求在队列中堆积,常见于脏页回写压力大、fsync 阻塞或 writeback 机制被触发
重点排查页缓存刷盘路径
Linux 的 page cache 在以下场景会强制落盘,引发毫秒到数百毫秒级延迟毛刺:
-
应用调用 fsync/fdatasync:数据库事务提交、日志 flush、配置保存等操作会同步等待数据写入磁盘。用
strace -p $PID -e trace=fsync,fdatasync,msync可捕获实时调用 -
内核 writeback 机制触发:当脏页比例(
/proc/sys/vm/dirty_ratio)或脏页存活时间(/proc/sys/vm/dirty_expire_centisecs)超限时,内核后台线程(kswapd、writeback)会集中刷盘。此时可能看到pdflush或writeback进程 CPU 升高 -
内存压力导致 direct reclaim + writeback:当可用内存不足,系统在分配内存时被迫同步回收脏页,造成“stop-the-world”式延迟。此时
pgpgout和pgmajfault会突增(用vmstat 1查)
用工具链定位具体源头
单纯看 request_time 毛刺无法下结论,需结合多层指标交叉验证:
-
查进程级 IO 行为:运行
pidstat -d 1,观察毛刺时刻哪个进程的kB_wr/s或IO/s突增;再用lsof -p $PID看它正在写哪些文件(如 journal、wal、log、tmp 文件) -
确认是否缓存干扰:对疑似文件做绕过缓存的测试:
dd if=/dev/zero of=testfile bs=4k count=1000 oflag=direct。若该命令也出现高延迟,说明是底层存储问题;若延迟正常,而普通写(无oflag=direct)延迟高,则基本锁定为 page cache 刷盘机制所致 -
抓取块层路径耗时:用
blktrace -d /dev/nvme0n1 -o - | blkparse -i -(需 root),重点关注Q→G(排队到获取请求)和I→C(下发到完成)的时间差。若Q→G大于 1ms,说明请求卡在队列里,常因调度器误配(如 NVMe 启用了mq-deadline)或驱动 bug;若I→C超长但dmesg有 PCIe AER 或 timeout 日志,则是硬件链路问题
快速验证与缓解建议
若确认是缓存 IO 导致的毛刺,可临时验证并缓解:
- 调大脏页缓冲窗口:
echo 30 > /proc/sys/vm/dirty_ratio(默认20),echo 6000 > /proc/sys/vm/dirty_expire_centisecs(默认3000,即30秒),让刷盘更平滑 - 禁用文件系统 barrier(仅限有 UPS 或电池保护的 SSD):
mount -o remount,barrier=0 /data,避免每次日志写都强制 sync - 挂载时加
noatime,nodiratime,commit=60,减少元数据更新频率 - 对数据库类应用,确保使用
O_DIRECT或direct=1(fio/dd),绕过 page cache,把控制权交还给应用自身缓存策略










