要真正实现高并发场景下的磁盘I/O读写带宽精准限速,必须使用cgroups硬性节流机制(throttle._bps_device和throttle._iops_device),而非仅依赖blkio.weight;权重仅在多容器争抢时调节优先级,单容器下无法限制峰值。

要真正实现高并发场景下的磁盘 I/O 读写带宽精准限速,不能依赖权重(blkio.weight),必须用 cgroups 的 硬性节流机制——即通过 throttle.read_bps_device/throttle.write_bps_device 和 throttle.read_iops_device/throttle.write_iops_device 直接设上限。权重只在多个容器争抢同一块盘时起调节作用,单容器下设再低也拦不住打满磁盘。
选对设备号和路径,节流才生效
规则写错位置或设备号不匹配,是节流失效最常见原因:
- 查设备主次号:运行
ls -l /dev/sda,若输出含8, 0,则设备号为8:0;NVMe 盘如/dev/nvme0n1通常是259:0,不可凭设备名猜测 - 确认 cgroup 版本:Docker 默认仍用 v1,路径为
/sys/fs/cgroup/blkio/docker/<container-id>/;若启用了 v2(Docker 20.10+ 可能默认),路径是/sys/fs/cgroup/docker/<container-id>/,混用会静默失败 - 操作时机:容器启动后 PID 稳定再写入,否则 cgroup 目录可能尚未创建
强制走 Direct I/O,绕过 PageCache 干扰
cgroups blkio throttle 仅对 Direct I/O 生效。常规文件操作(如 echo > file、cp、rsync 默认模式)走 Buffered I/O,数据先进 PageCache,后续刷盘由内核调度,blkio 完全无法干预。
- 天然适配的场景:MySQL(
innodb_flush_method=O_DIRECT)、PostgreSQL、MongoDB 默认配置、dd oflag=direct - 普通应用需改造:要么改用支持
O_DIRECT的工具,要么配合调内核参数(如vm.dirty_ratio控制脏页回写节奏) - 验证务必加
oflag=direct:例如dd if=/dev/zero of=/mnt/test bs=4k count=10000 oflag=direct
IOPS 与 BPS 必须组合设置
只限 IOPS 容易放行大 IO 请求占满带宽,只限 BPS 压不住高频小 IO —— 高并发下二者缺一不可:
- 写 IOPS 限制:例如
echo "8:0 200" > /sys/fs/cgroup/blkio/docker/abc123/blkio.throttle.write_iops_device - 写带宽限制:例如
echo "8:0 52428800" > /sys/fs/cgroup/blkio/docker/abc123/blkio.throttle.write_bps_device(即 50MB/s) - 读同理,建议同时配置
read_iops_device和read_bps_device
运行时直接限速更可靠
相比手动改 cgroup 文件,启动容器时用 Docker 原生参数更稳定、可复现:
- 限制写带宽:
docker run --device-write-bps /dev/sda:50mb ... - 限制读带宽:
docker run --device-read-bps /dev/sda:30mb ... - 限制写 IOPS:
docker run --device-write-iops /dev/sda:1000 ... - 限制读 IOPS:
docker run --device-read-iops /dev/sda:800 ... - 注意:参数中设备路径必须与宿主机实际设备一致,SSD/NVMe 需用
/dev/nvme0n1等对应路径


















