4.8.2 磁盘调度与内核I/O栈优化
磁盘调度与内核I/O栈优化#
磁盘调度器与内核 I/O 栈决定 I/O 请求的合并、排序与派发方式,直接影响延迟与吞吐。优化目标需与业务特征一致:数据库更看重低延迟,批量处理更看重吞吐。
1. I/O 栈原理与调度器位置(原理草图)
2. 调度器与内核I/O栈基础
- I/O 路径:应用 → VFS → 页缓存 → 块层 → 调度器 → 驱动 → 设备
- 常见调度器:
- mq-deadline:兼顾延迟与吞吐,适合通用服务器
- none:绕过调度,适合 NVMe/高速存储
- bfq:桌面交互友好,服务器慎用
- blk-mq 多队列:多核并发下提升吞吐,注意队列深度与队列数
3. 基础检查与识别(带命令解释)
# 识别磁盘类型与队列能力
lsblk -o NAME,ROTA,DISC-ALN,DISC-MAX,DISC-GRAN,TYPE,MOUNTPOINT
# ROTA=1 为机械盘,ROTA=0 为 SSD/NVMe
# 查看当前调度器(方括号为当前生效)
cat /sys/block/sdX/queue/scheduler
# 关键队列与预读参数
cat /sys/block/sdX/queue/nr_requests
cat /sys/block/sdX/queue/read_ahead_kb
命令解释
- lsblk:显示磁盘属性,ROTA 判断是否旋转盘。
- scheduler:显示当前调度器。
- nr_requests:队列深度,影响并发请求数。
- read_ahead_kb:顺序读预读大小。
4. 调度器切换与验证(示例)
# 临时切换为 mq-deadline(重启失效)
echo mq-deadline | sudo tee /sys/block/sdX/queue/scheduler
# 验证
cat /sys/block/sdX/queue/scheduler
# 预期:显示 [mq-deadline] 或 [none]
持久化切换(以 systemd-udev 规则为例)
# 创建规则(以 sdX 为例,实际可按模型匹配)
sudo tee /etc/udev/rules.d/60-io-scheduler.rules << 'EOF'
ACTION=="add|change", KERNEL=="sdX", ATTR{queue/scheduler}="mq-deadline"
EOF
# 重新加载并触发
sudo udevadm control --reload-rules
sudo udevadm trigger --type=devices --action=change /dev/sdX
# 验证
cat /sys/block/sdX/queue/scheduler
命令解释
- udev 规则让设备上线时应用调度器,避免重启丢失配置。
5. 关键内核参数优化(示例 + 解释)
# 查看与设置脏页写回策略(临时生效)
sysctl vm.dirty_ratio
sysctl vm.dirty_background_ratio
sysctl vm.dirty_expire_centisecs
sysctl vm.dirty_writeback_centisecs
# 示例:降低在线业务抖动
sudo sysctl -w vm.dirty_ratio=15
sudo sysctl -w vm.dirty_background_ratio=5
sudo sysctl -w vm.dirty_expire_centisecs=3000
sudo sysctl -w vm.dirty_writeback_centisecs=500
命令解释
- dirty_ratio:允许脏页占比上限,过大可能写回抖动。
- dirty_background_ratio:后台写回阈值。
- dirty_expire_centisecs:脏页最长驻留时间。
- dirty_writeback_centisecs:周期性写回频率。
6. I/O 优先级控制(示例)
# 将备份进程降为最低优先级(Class=3 idle)
sudo ionice -c3 -p $(pgrep -f backup.sh)
# 指定新进程以低优先级运行
sudo ionice -c2 -n7 tar -czf /backup/data.tar.gz /data
命令解释
- ionice:调整 I/O 调度优先级,避免后台任务抢占。
7. 性能验证与基线对比(安装 + 命令 + 预期)
# 安装常用工具(Debian/Ubuntu)
sudo apt-get update
sudo apt-get install -y sysstat iotop blktrace
# 安装常用工具(RHEL/CentOS)
sudo yum install -y sysstat iotop blktrace
# 实时查看磁盘延迟与队列深度
iostat -x 1 5
# 关注:await(延迟)、svctm、avgqu-sz
# 观察进程 I/O
sudo iotop -oPa
预期效果
- 切换调度器或调整队列后,await、avgqu-sz、%util 变化应与目标一致。
8. 排错场景与处理(示例)
- 问题:await 高、avgqu-sz 高、%util 接近 100%
- 可能原因:队列过小或写回过于集中
- 处理:
# 增大队列深度(临时)
echo 1024 | sudo tee /sys/block/sdX/queue/nr_requests
# 调整写回节奏
sudo sysctl -w vm.dirty_ratio=10
sudo sysctl -w vm.dirty_background_ratio=5
- 问题:随机 I/O 延迟升高
- 可能原因:预读过大
- 处理:
echo 16 | sudo tee /sys/block/sdX/queue/read_ahead_kb
9. 场景化优化示例
- 数据库(MySQL/Redis)
- 目标:低延迟
# SSD/NVMe:优先 none 或 mq-deadline
echo none | sudo tee /sys/block/nvme0n1/queue/scheduler
echo 16 | sudo tee /sys/block/nvme0n1/queue/read_ahead_kb
sudo sysctl -w vm.dirty_ratio=10
sudo sysctl -w vm.dirty_background_ratio=5
- 日志与备份
- 目标:高吞吐
echo mq-deadline | sudo tee /sys/block/sdX/queue/scheduler
echo 1024 | sudo tee /sys/block/sdX/queue/nr_requests
echo 256 | sudo tee /sys/block/sdX/queue/read_ahead_kb
10. 练习(可操作)
1. 记录当前调度器与 iostat -x 基线指标(await、avgqu-sz)。
2. 将 SSD 调度器切换为 none,预读设为 16,记录变化。
3. 将 HDD 调度器切换为 mq-deadline,预读设为 256,记录变化。
4. 使用 ionice 降低备份任务优先级,观察在线请求延迟变化。
5. 回滚所有改动,确保指标恢复到基线。
11. 回滚与变更管理
# 回滚调度器
echo mq-deadline | sudo tee /sys/block/sdX/queue/scheduler
# 回滚预读与队列深度
echo 128 | sudo tee /sys/block/sdX/queue/read_ahead_kb
echo 128 | sudo tee /sys/block/sdX/queue/nr_requests
# 回滚写回参数(示例)
sudo sysctl -w vm.dirty_ratio=20
sudo sysctl -w vm.dirty_background_ratio=10
sudo sysctl -w vm.dirty_expire_centisecs=3000
sudo sysctl -w vm.dirty_writeback_centisecs=500
确保每次变更有记录、可回滚,并以业务指标验证效果。