必须依据文件系统 mtime 判断 rdb 过期,而非文件名日期;删除前须用 config get 获取 redis 实际加载路径并排除,配合 lsof 检查句柄占用,再通过 find -not -samefile 安全清理。

Redis RDB 文件过期判断不能只看文件名里的时间戳
Redis 自身不记录 RDB 文件的生成时间元数据,dump.rdb 或 dump-2024-06-15.rdb 这类命名只是人工约定,脚本必须依赖文件系统层面的 mtime(最后修改时间)来判断是否过期——这才是真实可靠的依据。
常见错误是解析文件名中的日期字符串再计算天数,结果遇到手动拷贝、重命名、NFS挂载时 mtime 被重置等情况,直接误删或漏删。
- 用
find /var/lib/redis/ -name "*.rdb" -mmin +1440比用date -d "2024-06-15" +%s解析更可靠 - 如果 Redis 配置了
dbfilename为非默认名(如redis-data.rdb),脚本中要同步更新匹配模式 - 注意:
mtime是文件内容最后一次被写入的时间,恰好对应 RDB 快照完成时刻,和ctime(元数据变更)或atime(访问时间)无关
删除前必须确认 Redis 当前正在使用的 RDB 文件
直接 find ... -delete 可能误删正在被 Redis 加载或写入的活跃快照,导致下次重启失败或数据丢失。必须先查出 Redis 实际加载的 RDB 路径,再排除它。
方法是读取 Redis 配置运行时值:redis-cli CONFIG GET dbfilename 和 redis-cli CONFIG GET dir,拼出完整路径;再用 readlink -f 处理软链接,确保比对准确。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 示例获取当前 RDB 路径:
REDIS_DIR=$(redis-cli CONFIG GET dir | tail -n 1) REDIS_FILE=$(redis-cli CONFIG GET dbfilename | tail -n 1) CURRENT_RDB=$(readlink -f "$REDIS_DIR/$REDIS_FILE")
- 在
find命令中用-not -samefile "$CURRENT_RDB"排除该文件(要求 GNU findutils ≥ 4.2.0) - 如果 Redis 正在做 bgsave,
dump.rdb可能处于临时写入状态,此时mtime尚未更新,但文件已存在——所以仅靠时间判断不够,排除当前配置指向的文件是硬性安全边界
Shell 脚本里要处理权限与并发风险
Redis 进程通常以 redis 用户运行,而清理脚本可能由 root 或定时任务用户执行。权限不一致会导致 find 扫描失败,或 rm 报 Permission denied 却静默跳过。
- 脚本开头加
set -e和set -u,任何命令失败立即退出,避免部分删除后流程继续 - 用
find ... -print0 | xargs -0 rm -f替代-delete,便于调试时把rm换成echo预览 - 加文件锁防止多个实例同时运行:
if ! flock -n 200; then echo "Another instance is running"; exit 1; fi exec 200>/var/lock/redis-rdb-cleanup.lock
- 不要把脚本放在
/var/lib/redis/下执行——该目录常为redis:redis所有,普通用户无法写入临时文件
crontab 定时任务必须指定 SHELL 和 PATH
系统级 cron 默认 PATH=/usr/bin:/bin,不含 /usr/local/bin 或 redis-cli 可能所在路径,导致 CONFIG GET 命令找不到。
也不要用 ~ 或 $HOME,cron 中这些变量未定义或为空。
- 推荐写法(放入
/etc/crontab):0 3 * * * root PATH="/usr/local/bin:/usr/bin:/bin" /usr/local/bin/redis-rdb-cleanup.sh --keep-days 7
- 脚本内用
getopt解析--keep-days参数,避免硬编码;默认保留 7 天,但生产环境建议设为 14 或 30,尤其在开启 AOF + RDB 混合持久化时 - 日志重定向到文件,比如
>/var/log/redis-rdb-cleanup.log 2>&1,否则 cron 错误只能查/var/log/syslog,难定位
真正麻烦的不是写删除逻辑,而是确认「这个 .rdb 文件此刻对 Redis 来说是不是可删的」——它可能正被加载、可能被监控工具轮询、也可能被备份系统临时 hardlink。每次清理前,lsof -p $(pgrep redis-server) | grep rdb 看是否有句柄打开,比任何时间规则都管用。










