最有效方式是用cgroups v2的io.max控制器做内核层硬限带宽,需确认系统启用cgroup2及io控制器、查准设备号(如8:0)、创建限速组并写入rbps/wbps值、迁移pid至该cgroup,最后通过io.stat和dd direct实测验证。

Linux磁盘I/O隔离最有效的方式,是用cgroups v2的io.max控制器做硬性带宽限制——它在内核块设备层拦截请求,不依赖进程行为、不受页缓存干扰,对dd、数据库写入、rsync等直接调用syscalls的场景完全生效。
确认系统支持cgroups v2 io控制器
不是所有系统默认启用v2的IO控制。需逐项验证:
- 运行
mount | grep cgroup,输出中必须含type cgroup2且挂载点为/sys/fs/cgroup或其子目录 - 运行
cat /proc/cgroups,检查io行的enabled列是否为1 - 若只看到
blkio(v1)而没有io(v2),需在内核启动参数中添加cgroup_no_v1=all并重启
设置设备级读写带宽限制
限制针对具体块设备,必须用主次设备号(如8:0对应/dev/sda,259:0对应/dev/nvme0n1):
- 查设备号:
ls -l /dev/sda→ 看到brw-rw---- 1 root disk 8, 0,即主次号为8:0 - 新建cgroup:
sudo mkdir -p /sys/fs/cgroup/limit-io - 设写入上限5MB/s:
echo "8:0 wbps=5242880" | sudo tee /sys/fs/cgroup/limit-io/io.max - 同时限读写:
echo "8:0 rbps=5242880 wbps=5242880" | sudo tee /sys/fs/cgroup/limit-io/io.max
将进程实时纳入限速组
无需重启进程,支持运行中迁移,但一个进程只能属于一个io cgroup:
- 获取PID:
pgrep -f "backup.sh"或pidof rsync - 迁移进组:
echo $PID | sudo tee /sys/fs/cgroup/limit-io/cgroup.procs - 验证归属:
cat /proc/$PID/cgroup | grep io应显示该cgroup路径 - 多线程进程整体受限;若失败,先检查该PID是否已在其他
iocgroup中(可清空原组的cgroup.procs)
验证限速是否真实生效
配置写入不等于效果落地,必须实测+统计双验证:
- 看实时统计:
cat /sys/fs/cgroup/limit-io/io.stat,关注rwbps=和wbps=字段是否接近设定值 - 用direct I/O测试:
dd if=/dev/zero of=/mnt/test bs=1M count=500 oflag=direct conv=fdatasync - 常见失效原因:设备号填错、进程未真正落在该cgroup、内核未编译
CONFIG_BLK_CGROUP_IO_CTRL(查zcat /proc/config.gz | grep IO_CTRL)











