redis无内置io限速机制,bgsave与bgrewriteaof子进程通过write()+fsync()直写磁盘,依赖内核调度;生产中可用ionice/cpulimit临时压制,或用cgroups v1/v2对进程组实施硬性io带宽限制。

Redis 本身不提供限速参数,bgsave 和 bgrewriteaof 子进程写磁盘完全由内核调度
Redis 没有像 PostgreSQL 的 bgwriter_delay 或 MySQL 的 innodb_io_capacity 那样的内置 IO 限速机制。它的 bgsave 和 bgrewriteaof 子进程在写临时 RDB/AOF 文件时,调用的是标准 write() + fsync(),全程无节流逻辑。这意味着:一旦触发,子进程会尽可能快地把数据刷到磁盘,尤其在 SSD 上可能瞬间打满 IO 带宽,挤占主进程响应或其它关键服务。
用 ionice + cpulimit 临时压制子进程 IO 优先级
这是生产环境中最直接、无需重启 Redis 的干预方式,适用于突发性 bgsave 导致的 IO 抖动:
- 先通过
ps aux | grep redis找到正在运行的bgsave子进程 PID(注意不是主进程,而是 fork 出来的、命令行含bgsave的那个) - 立即降低其 IO 优先级:
ionice -c2 -n7 -p <pid></pid>(-c2表示 best-effort 类,-n7是最低 IO niceness) - 如需进一步抑制写入吞吐,可叠加 CPU 限频:
cpulimit -p <pid> -l 5</pid>(限制最多使用 5% CPU,间接拖慢 write 调用频率) - 该操作对已开始的子进程生效,但下次
bgsave还得重做——适合救急,不适合长期策略
用 cgroups v1 对 Redis 进程组做全局 IO 带宽隔离(推荐长期方案)
Linux cgroups v1 的 blkio.weight 或 blkio.throttle.write_bps_device 可以硬性限制某进程对指定块设备的写入速率。相比临时命令,它稳定、可持久化,且作用于整个 Redis 进程树(含所有 fork 出的子进程):
- 确认你的系统启用
blkiocontroller:ls /sys/fs/cgroup/blkio/ - 创建限制组并设写入上限(例如限制为 20MB/s 到
/dev/sda):echo '8:0 20971520' > /sys/fs/cgroup/blkio/redis-limited/blkio.throttle.write_bps_device(其中8:0是sda的 major:minor 号,用ls -l /dev/sd*查) - 把 Redis 主进程 PID 加入该组:
echo <redis_pid> > /sys/fs/cgroup/blkio/redis-limited/cgroup.procs</redis_pid> - 后续所有由该 Redis 进程 fork 的子进程(包括
bgsave)都会继承此 IO 限额
注意:cgroups v2 默认不兼容 v1 接口,若系统已启用 v2,需改用 io.max(语法不同),且需确保 Redis 进程启动前已加入对应 controller。
为什么不用 no-appendfsync-on-rewrite 或调整 appendfsync 来“限速”?
这两个配置解决的是 AOF 日志刷盘与重写的冲突问题,不是带宽控制手段:
-
no-appendfsync-on-rewrite yes的作用是:当bgrewriteaof运行时,暂停主线程的fsync,避免两个 fsync 同时争抢磁盘;但它不限制bgrewriteaof自身的 write 速度 -
appendfsync everysec控制的是 AOF buf 写入内核 buffer 的频率,不是写盘速率;实际落盘仍依赖内核 page cache 回写策略,无法精确控速 - 试图靠调大
save间隔来“减少写入”是治标不治本——只要数据量增长,单次 bgsave 的写入总量和峰值带宽不会变小
真正要压住磁盘写入带宽,必须从 OS 层面对进程 IO 行为做硬性约束,而不是寄希望于 Redis 内部的同步策略开关。











