Linux IO调度器调优需据workload、存储介质等匹配:HDD用mq-deadline,SATA SSD选mq-deadline或kyber,NVMe优先none;参数调整须测试验证,关注await与avgqu-sz而非仅%util。

Linux IO调度器调优不是“选一个最快算法”就完事,关键看 workload 类型、存储介质(HDD/SSD/NVMe)、队列深度和应用IO模式(随机小IO多?顺序大IO多?延迟敏感还是吞吐优先?)。盲目切换调度器可能反而降低性能。
先确认当前调度器和可用选项
查看当前设备的IO调度器:
cat /sys/block/sda/queue/scheduler输出类似 [mq-deadline] kyber bfq none,方括号内是当前激活的调度器。不同内核版本支持不同调度器:
- mq-deadline:多队列环境下的经典deadline变种,兼顾延迟与吞吐,HDD和部分SSD场景较稳
- kyber:专为低延迟设计,适合NVMe等极低延迟设备,对延迟敏感型服务(如数据库事务)友好
- bfq:强调公平性与交互响应,适合多用户、混合负载(如桌面、虚拟机宿主),但高并发纯IO场景可能吞吐略低
- none:绕过内核IO调度,直接交由设备自身队列管理(如NVMe native queue),通常推荐用于现代SSD/NVMe
按存储类型选择策略
HDD(机械盘):磁头寻道代价高,优先减少随机寻道。mq-deadline 是较稳妥选择;若业务含大量小文件读写且延迟敏感,可试 bfq 并调大 slice_idle_us 避免过度抢占。
SATA SSD:无寻道延迟,但存在写放大和队列竞争。mq-deadline 或 kyber 均可;避免用 bfq(其公平机制在SSD上收益有限,反增开销)。
NVMe SSD:原生支持数千队列,内核调度意义下降。直接设为 none 最常见也最推荐;若需精细控制(如隔离容器IO),再考虑 kyber 并配合 cgroup v2 io.weight 调节。
关键参数微调(以 mq-deadline 为例)
仅在明确瓶颈且测试验证后调整,勿凭经验乱改:
- echo 200000 > /sys/block/sda/queue/iosched/read_expire —— 增加读请求超时(单位μs),缓解突发读延迟抖动
- echo 500000 > /sys/block/sda/queue/iosched/write_expire —— 写请求容忍更长等待,利于合并,适合日志类顺序写
- echo 1 > /sys/block/sda/queue/iosched/fifo_batch —— 减小批量处理数,提升响应性(小IO多时)
所有修改重启失效,需写入 udev 规则或启动脚本持久化。
验证效果不能只看 iostat %util
%util 接近100%不等于瓶颈,可能是调度器主动限流或设备真实饱和。重点观察:
- await 和 r_await/w_await:持续高于 10ms(HDD)或 1ms(SSD)说明IO延迟异常
- svctm(已弃用,参考意义弱)→ 改看 avgqu-sz:队列长期 > 1 表示请求积压,结合 await 判断是调度器堵还是设备慢
- 用 iostat -x 1 + blktrace 定位具体IO模式(如大量4K随机写),再匹配调度器特性










