Redis RDB快照文件不能直接删除,因为可能误删正在写入的temp-*.rdb临时文件或尚未加载确认的有效快照,导致数据恢复失败;安全清理需结合INFO persistence状态、排除当前文件及临时文件,并按时间(如-mmin)精确筛选。

Redis RDB快照文件为什么不能直接删?
因为 redis.conf 里 dbfilename 和 dir 共同决定了当前正在写入的 RDB 文件路径,但 Redis 不会自动管理历史快照——它只管覆盖或新建,不管旧文件。直接用 rm *.rdb 可能误删正在被 SAVE 或 BGSAVE 写入的临时文件(比如 temp-12345.rdb),也可能删掉还没被主进程加载确认的上一份快照,导致恢复失败。
真正安全的做法是:只清理「已确认完成、且超过保留时限」的快照,且避开 Redis 正在操作的文件名模式。
-
redis-cli INFO persistence中的rdb_last_save_time和rdb_bgsave_in_progress是判断依据 - Redis 进程启动时会读取
dbfilename指定的文件,所以那个文件一定不能删 - 临时文件名通常是
temp-*.rdb,必须跳过
Shell 脚本怎么安全识别可删除的 RDB 文件?
核心逻辑不是“找 .rdb 后缀”,而是“找符合命名规则 + 时间戳可解析 + 不在 Redis 当前使用列表中”的文件。推荐用 find 配合 -name 和 -mtime,但要注意:
- 别用
-mtime +7算“7天前”,它按 24 小时整数倍截断,可能漏掉刚过 6 天 23 小时的文件;改用-mmin +10080(精确到分钟)更稳 - 必须排除
temp-*.rdb和dump.rdb(默认dbfilename值)——后者是当前有效快照 - 如果改过
dbfilename(比如设成myapp.rdb),脚本里得同步更新排除名单
示例片段(假设 dir /var/lib/redis,保留最近 3 天):
find /var/lib/redis -name "*.rdb" \ ! -name "dump.rdb" \ ! -name "temp-*.rdb" \ -mmin +4320 \ -delete
如何避免脚本和 Redis 写入冲突?
最简单的办法是让脚本只在 BGSAVE 不活跃时运行,否则可能删到一半被新快照覆盖,或者删完立刻触发一次 BGSAVE 导致磁盘爆满。检查方式就是读 redis-cli INFO persistence 的输出:
- 当
rdb_bgsave_in_progress:1时,跳过本次清理 - 用
grep -q "rdb_bgsave_in_progress:0"判断比解析 JSON 更轻量 - 加个
sleep 30重试最多 2 次,避免因瞬时繁忙错过执行窗口 - 不要把清理脚本和
save触发条件(如save 900 1)放在同一台机器高频调度,容易形成 I/O 尖峰
为什么轮转策略建议用时间而非数量?
因为 RDB 文件大小波动极大:空实例几 KB,大实例可达几十 GB。固定保留 5 个文件,可能占满 200GB 磁盘;而按时间(比如 72 小时)能自然适配业务写入节奏。但要注意:
-
SAVE是阻塞的,生产环境几乎不用;BGSAVE是 fork 子进程,内存翻倍风险存在,所以不能靠频繁快照来“多留几个” - 如果用 AOF + RDB 混合持久化,
appendfilename和dbfilename的路径最好分开,避免清理脚本误伤 AOF 日志 - 云环境(如 AWS EBS)要注意快照清理后磁盘空间不会立即释放,需配合
fstrim(仅限支持 TRIM 的文件系统)
实际部署时,最容易被忽略的是 Redis 配置里的 dir 权限——脚本用什么用户跑,就得确保该用户对 dir 有读写权限,且不能依赖 root。否则 cron 里看着执行成功,其实一个文件都没删掉。

















