根本原因是fork()系统调用需同步复制页表,内存越大页表越庞大,耗时越长,导致主线程阻塞;8gb以上实例fork常达200ms–1s+,远超redis默认超时阈值,表现为ping超时、延迟飙升、cpu瞬时冲高。

为什么大内存实例执行bgsave会卡住主线程
不是bgsave本身慢,而是fork子进程时操作系统要复制父进程的页表——内存越大,页表越庞大,复制耗时越长。Redis主线程在这段时间内完全阻塞,表现为客户端请求超时、延迟飙升。
常见现象:INFO persistence中rdb_bgsave_in_progress仍为0,但redis-cli ping已超时;或top看到redis-server CPU瞬间冲高后回落。
- 8GB以上内存实例,fork可能耗时200ms–1s+,远超Redis默认
timeout(通常30–60ms) - Linux内核版本低于4.12时,页表复制无优化,问题更明显
- 启用
vm.overcommit_memory=1可缓解,但不能根治
save配置在大数据量下必须精简
RDB不是“开就完事”,高频小快照在数据量大时等于持续制造压力。默认save 900 1看似宽松,但只要每15分钟改1个key,就会触发一次bgsave——而每次fork都在重复消耗CPU和内存。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 把
save 900 1改成save 3600 1000,大幅降低触发频率 - 线上主节点建议禁用自动save:设
save "",只在从节点或备份专用实例上保留 - 若必须保RDB,配合AOF重写周期(
auto-aof-rewrite-percentage)错峰安排
rdbcompression yes不是万能解药
开启压缩确实能减小dump.rdb体积,但对fork阶段毫无帮助——它只影响子进程写入磁盘前的编码阶段。反而可能延长子进程生命周期,加重COW内存压力。
- Redis 7.0+用zstd压缩比lz4再省15%–25%体积,但fork后子进程CPU占用更高
-
rdbchecksum yes必须保持开启,关掉它既不减体积,还失去校验能力 - 压缩率提升≠启动变快:加载时解压仍需CPU,大RDB文件反而可能拖慢恢复
真正该查的不是配置,是KEYS *
配置调得再细,如果内存里存了10万条log:20260713:*没过期,RDB照样膨胀。RDB大小反映的是“此刻内存真实占用”,不是“你认为该有的数据量”。
- 用
redis-cli --scan --pattern "tmp:*"快速扫临时key -
MEMORY USAGE key逐个查大户,重点关注HGETALL返回超1MB的Hash -
redis-cli memory stats看total_allocated与used_memory差值,判断碎片是否严重
别在redis.conf里反复调rdbcompression,先跑一遍KEYS *或SCAN——RDB到底为什么大,数据自己会说话。










