记录一下那天晚上的排查过程。阿里云 ESSD PL1 盘上跑数据库压测,iostat -x 显示 util 只有四成,r_await 却有 18ms,明显没跑满盘的 IOPS,加大并发后 await 又继续涨。
刚开始盯着「文件系统预读太小,每次都要等一次完整往返」,折腾了半个多小时,排掉了。
排查方向其实有限,先把可能性排一排。单线程同步读,队列里始终只有一个请求,盘的并行能力用不上。少数情况下是应用的 IO 大小是 4K 随机读,正好踩在盘的最差队列模型上。
另外,cgroup 的 io.max 给这个容器限了 IOPS,超出的请求排队。
第一件事是看并发与延迟的对应关系
iostat -x 1 5 /dev/vdb
再往下确认没有 cgroup 层的 IO 限速
cat /sys/fs/cgroup/io.max 2>/dev/null || systemctl status docker | head
接着用 fio 压不同深度对比 IOPS
fio --name=q32 --filename=/data/test.img --rw=randread --bs=4k --iodepth=32 --numjobs=4 --runtime=60 --time_based
剩下的就是把应用侧的读并发提上去再观察
iostat -x 1 5 /dev/vdb | tail -5
怎么算真的好了,看的是同一批现象。深度提到 32 后 fio 的 iops 接近盘标称值、clat p99 在可接受范围,应用的 util 上升到七成以上而 await 不再线性恶化。
提醒一点。await 高不等于盘慢,先确认是不是自己只发了一个请求;云盘的 IOPS 和时延是随深度变化的曲线,只看单点没有意义。改动前把原配置备份一份,出问题能马上回滚,这比任何技巧都实用。