Redis RDB快照和AOF重写均因fork触发写时复制(COW),导致内存峰值接近2倍,需通过vm.overcommit_memory=1、监控rss与used_memory比值、低峰期调度及合理maxmemory策略来规避OOM风险。

Redis RDB快照期间内存翻倍风险
RDB持久化在 fork 子进程时会触发写时复制(COW),如果主线程在保存期间大量修改数据,子进程页表会持续复制物理内存页,导致实际内存占用可能接近峰值的 2 倍。这不是 bug,而是 Linux 内存管理机制决定的。
常见现象:Used memory peak 突增、OOM killed process redis-server 日志出现、系统 free -h 显示可用内存骤降。
- 避免在业务高峰期执行
SAVE;改用BGSAVE,但也要注意其 COW 开销 - 设置
vm.overcommit_memory = 1(Linux 内核参数),允许 fork 分配虚拟内存而不校验物理内存是否足够 - 监控
mem_allocator和used_memory_rss差值,若used_memory_rss / used_memory> 2.5,说明 COW 副本已严重膨胀
Redis AOF重写时的内存与磁盘双重压力
AOF rewrite(BGREWRITEAOF)同样依赖 fork,且重写过程需构建新 AOF 文件的内存缓冲区,同时还要维持旧 AOF 的 fsync 和新 AOF 的写入。当 key 数量大、value 大或存在大量 set/get 操作时,极易打满内存或 I/O。
典型错误:Can't rewrite append only file: No space left on device(磁盘满)或 Failed to rewrite the append only file: fork: Cannot allocate memory(内存不足)。
- 关闭自动重写触发:设
auto-aof-rewrite-percentage 0,改由运维定时在低峰期手动触发BGREWRITEAOF - 限制重写缓冲区大小:配置
aof-rewrite-incremental-fsync yes,让重写过程分批 fsync,降低单次 I/O 峰值 - 确保
aof-rewrite-temp-file所在磁盘有 ≥ 2 倍当前 AOF 文件大小的空闲空间
如何用 memory limit + maxmemory-policy 控制 OOM 边界
仅靠 OS OOM killer 是被动且不可控的。Redis 提供 maxmemory 主动限流机制,配合策略可避免 crash,但选错策略会导致业务异常。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
例如:设 maxmemory 2gb 但用 noeviction,写入超限时直接返回 (error) OOM command not allowed when used memory > 'maxmemory';而用 allkeys-lru 可能误删热点 key。
- 优先选
volatile-lru或volatile-ttl,只驱逐带过期时间的 key,保护常驻缓存 - 如必须用 allkeys 类策略,务必确认业务能容忍随机 key 被删——比如 session 缓存不适用
- 配合
maxmemory-samples 10(默认 5),提升 LRU 采样精度,减少误删概率 - 上线前压测:用
redis-benchmark -n 1000000 -t set,get观察evicted_keys是否非零增长
混合持久化(aof-use-rdb-preamble)对内存的实际影响
开启 aof-use-rdb-preamble yes 后,AOF rewrite 会先生成一个 RDB 格式头部,再追加增量命令。这减少了 AOF 文件体积和加载时间,但 RDB 头部生成仍需 fork + COW,且内存中要同时维护 RDB 序列化缓冲区和 AOF 命令缓冲区。
实测显示:在 4GB 数据集上启用该选项,AOF rewrite 过程中 RSS 峰值比纯 AOF 高出约 15–20%,但加载速度提升 3x+。
- 仅当 AOF 文件过大(> 1GB)、重启恢复慢到影响 SLA 时才启用
- 必须搭配
auto-aof-rewrite-percentage 0和人工调度,否则自动触发时机不可控 - 升级 Redis 版本前验证:4.0+ 支持该选项,3.x 不识别,会导致 AOF 加载失败
真正难处理的不是配置本身,而是 COW 在不同负载模式下的非线性放大效应——一次批量 set 可能比等量分散写入多占 3 倍内存。观测 used_memory_peak 和 mem_fragmentation_ratio 比调参数更重要。

















