io-scheduler

查看和切换块设备 I/O 调度器,理解队列、合并与延迟取舍

补充说明

I/O 调度器(elevator)决定块层如何合并、排序和分发请求。现代内核使用 blk-mq 多队列框架,常见可选值为 none、mq-deadline、kyber、bfq(具体取决于内核配置);旧的 noop、deadline、cfq 已在 5.0 随传统单队列块层一并移除,由上述 blk-mq 调度器取代。

常用示例

# 查看设备当前调度器(方括号内为当前值)
cat /sys/block/nvme0n1/queue/scheduler

# 查看设备是否旋转盘、当前调度器和容量(SCHED 列需较新的 util-linux)
lsblk -d -o NAME,ROTA,SCHED,SIZE

# 切换为 mq-deadline(虚拟盘先确认底层不会覆盖)
echo mq-deadline | sudo tee /sys/block/vda/queue/scheduler

# 查看预读和队列请求数
cat /sys/block/vda/queue/read_ahead_kb
cat /sys/block/vda/queue/nr_requests

# 用 udev 规则持久化:写入 /etc/udev/rules.d/60-iosched.rules
# ACTION=="add|change", KERNEL=="vda", ATTR{queue/scheduler}="mq-deadline"

# 观察调度效果:await、aqu-sz 与 %util 的变化
iostat -xz 1 5

ionice 设置的是 ioprio,但 none 调度器基本不理会它;容器场景更可靠的是 cgroup v2 的 io.max/io.weight。

易错点与排错

读完自测

  1. none 调度器适合什么设备,为什么?
  2. 为什么用 ionice 给容器限流通常不可靠?
  3. 切换调度器后应该看哪些指标判断是否有效?
答案
  1. 适合 NVMe 等具备深队列和自身调度能力的设备;none 避免内核层额外排序,降低延迟和 CPU 开销。
  2. ionice 依赖块层调度器解释 ioprio,none 等调度器不处理;容器应按 cgroup v2 的 io.max/io.weight 限流。
  3. 看 iostat -xz 的 r_await/w_await、aqu-sz、%util,以及应用侧 P99 延迟和吞吐;同时排除云盘限流。

相关条目