SAVE 与 BGSAVE 的区别
两者都生成 RDB 快照,区别在于由谁来完成写盘:SAVE 在服务进程内同步执行,从遍历数据到写完文件的全过程主线程都被占用,期间任何请求都无法处理;BGSAVE 则 fork 一个子进程去遍历内存并写文件,主进程在 fork 完成的那一刻就恢复服务。因此生产环境正常运行期的快照一律使用 BGSAVE,SAVE 只在停机维护或明确知道可以接受阻塞的场景里使用。
基本信息
| SAVE | 同步执行,全程阻塞主线程,返回时快照已完成 |
|---|---|
| BGSAVE | fork 子进程后台执行,主进程仅 fork 瞬间停顿 |
| 失败可见性 | SAVE 同步报错可直接感知,BGSAVE 结果写入 rdb_last_bgsave_status |
| 重复调用 | BGSAVE 进行中再次调用会直接返回已在进行中的提示 |
| 互斥关系 | BGSAVE 与 BGREWRITEAOF 不会同时执行子进程任务 |
典型使用场景
- 日常快照:使用 BGSAVE 或依赖 save 配置自动触发,业务几乎无感
- 停机维护前手工留档:实例即将停止服务时用 SAVE 确保快照确实写完
- 容器编排的停止钩子:停止前触发一次快照,避免依赖进程退出时的默认行为
- 故障排查:用 LASTSAVE 确认距离上次成功快照已经过了多久
- 验证快照结果:读 rdb_last_bgsave_status 判断后台任务是否成功
触发与核对
触发与核对
redis-cli BGSAVE # 后台快照,立即返回
redis-cli LASTSAVE # 上次成功快照的时间戳
redis-cli INFO persistence | grep -E 'rdb_last_bgsave_status|rdb_bgsave_in_progress'
redis-cli INFO persistence | grep rdb_last_save_time
redis-cli SAVE # 仅停机维护时使用,会阻塞服务
redis-cli INFO memory | grep used_memory_rss # 快照期间 RSS 会短时上升对比
| 维度 | SAVE | BGSAVE |
|---|---|---|
| 阻塞范围 | 全程阻塞主线程 | 仅 fork 瞬间停顿 |
| 适用场景 | 停机维护、离线导出 | 生产常态快照 |
| 失败感知 | 同步报错,调用方立刻知道 | 通过状态字段与监控告警发现 |
| 内存影响 | 无 COW 增量 | 快照期间的写入会产生 COW 副本 |
| 耗时感知 | 命令返回即完成 | 需查进度字段确认是否结束 |
快照期间的内存变化:BGSAVE 的子进程读取的是 fork 时刻的内存视图,主进程在此时刻之后修改的页面会触发写时复制,产生额外副本,因此 used_memory_rss 会短时上升。写入越猛烈增长越明显,这是容量规划必须考虑的部分。
在生产实例上执行 SAVE 会造成秒级甚至更长的完全阻塞,所有客户端请求排队等待,往往被误判为网络故障或实例宕机。除非实例已经准备下线,否则不要使用 SAVE。