等待时间要拆开看
一次 IO 的总耗时由三段构成:请求进入队列后的排队时间、设备(含后端存储)实际服务时间、以及主机与链路传输开销。iostat 给出的 await 是前两段之和,所以同一个 await 数值可能是「设备很慢」也可能是「请求在排队等着」。归因的目标就是把这三段分开,判断该优化哪些参数:降排队要减少并发或提升后端能力,降服务时间才涉及介质与缓存优化。
基本信息
| 时间构成 | 排队等待 + 设备服务 + 链路传输 |
|---|---|
| 主机侧观测 | iostat 的时延与队列列、iotop、blktrace |
| 调度侧观测 | CPU 等待占比、IO 压力指标(/proc/pressure/io) |
| 常见工具 | iostat、blktrace 与 blkparse、bpftrace、iotop |
| 适用范围 | Linux;工具与字段以对应版本手册为准 |
典型使用场景
- 应用超时但磁盘利用率不高:确认时间消耗在排队还是后端
- 数据库提交慢:区分日志同步写与数据文件读的等待构成
- 虚拟机与容器抖动:确认是共享后端还是本机资源竞争
- 压测中时延拐点分析:验证哪一段先饱和
- 故障定位:判断是介质退化还是瞬时请求风暴
分段归因的常用手段
分段归因的常用手段
iostat -x 1 5 # 结合 r_await/w_await 与队列列看排队占比
iotop -o -d 2 # 找出持续发起 IO 的进程
cat /proc/pressure/io # 系统级 IO 压力:some 与 full 两行
dd if=/dev/zero of=/tmp/t bs=1M count=2048 oflag=direct # 直写测底噪
blktrace -d /dev/sdb -o - | blkparse -i - # 逐请求看各阶段耗时
bpftrace -e 'tracepoint:block:block_rq_issue { @[comm] = count(); }' # 按进程统计等待构成对照
| 观察 | 倾向的结论 | 下一步 |
|---|---|---|
| 队列列高且时延高 | 排队主导,链路已饱和 | 降并发或扩容后端 |
| 队列低但时延高 | 服务时间主导,介质或后端慢 | 查介质健康与后端处理 |
| 写入时延高于读取 | 写路径含回写、日志与同步等待 | 检查刷盘策略与写放大 |
| 单进程时延高、全局正常 | 该进程自身请求模式或堆积问题 | 分析进程的请求大小与并发 |
| IO 压力高但 CPU 等待占比低 | 多核环境下等待被摊薄 | 以压力指标与分位时延为准 |
CPU 的等待占比是「空闲且有未完成 IO」的时间比例,多核与高并发环境下会明显偏低,不能作为唯一判据;观察 IO 压力与高分位时延更可靠。
归因时要固定请求模式:块大小、读写比、顺序与随机、是否直写,任何一项变化都会改变时延构成,混测得出的结论无法复现。