不能只靠SAVE或BGSAVE完成备份,因二者仅生成无时间戳、不跨机、不清理旧文件的本地快照;需结合crontab调用脚本实现触发快照、等待完成、带时间戳拷贝校验、上传及定期清理。
不能只靠 SAVE 或 BGSAVE 命令就认为备份完成了——它们只生成本地快照,不带时间戳、不跨机、不清理旧文件,更不会自动上传到远程服务器。
很多脚本只写 redis-cli bgsave 就以为万事大吉,但实际会遇到这些问题:
BGSAVE 成功后,dump.rdb 仍留在 Redis 的 dir 目录(如 /var/redis/6379/),同名覆盖,无历史版本cp 过程中 BGSAVE 正在写入新 RDB,可能复制出损坏文件(虽然 Redis 用临时文件 + rename 保证原子性,但外部 cp 仍需避开写入窗口)cp 完就走,结果传了个空文件或截断文件过去scp: Connection refused 却没人发现核心是三步:触发快照 → 等待完成 → 拷贝+重命名+校验 → 上传。关键不是“立刻 cp”,而是等 BGSAVE 真正结束。
redis-cli bgsave 触发,再用 redis-cli lastsave 拿到上一次成功快照的 Unix 时间戳,轮询对比确认完成(避免 sleep 2 这种不可靠等待)date +%Y%m%d%H%M%S 生成唯一文件名,例如 dump-20260713110522.rdb,避免覆盖redis-check-rdb /path/to/copy.rdb,返回非 0 就中止上传,防止传坏文件rsync -avz --remove-source-files 比 scp 更稳妥:支持断点续传、失败不删源、可加 --timeout=30
user@backup-server:/backup/redis/2026/07/13/,方便按月归档和清理常见错误是把所有逻辑塞进一行 crontab,或忽略 shell 环境差异(crontab 默认 $PATH 极简)。正确做法:
0 * * * * /usr/local/redis/copy/upload_rdb_hourly.sh,不写 sh 前缀#!/bin/bash + export PATH="/usr/local/bin:/usr/bin:/bin"
dir 和 dbfilename,别依赖默认值;用 redis-cli CONFIG GET dir 和 CONFIG GET dbfilename 动态获取,而非硬编码 /var/redis/6379/dump.rdb
ssh-copy-id),且远程目录存在、有写权限;脚本里用 mkdir -p 创建父目录,但不要用 sudo —— crontab 以 redis 用户运行,不该提权真正麻烦的不是写脚本,而是验证上传后的 RDB 能否被 redis-check-rdb 读通、能否在另一台机器上用 redis-server --test-memory 加载成功——这些必须定期抽样测,不能只看 crontab 日志里有没有报错。