线上Redis误执行了FLUSHALL命令,导致数据全部被清空,如何利用AOF文件紧急恢复数据?
这是一项非常紧急的线上救援操作。请立刻停止当前的恐慌,深呼吸,并严格按照以下步骤操作。
⚠️ 最核心的警告:绝对不要在此时重启 Redis!
如果直接重启,Redis 会重新执行 AOF 文件中的命令(包括那条 FLUSHALL),导致数据彻底无法恢复。更糟的是,如果触发了 AOF 自动重写(BGREWRITEAOF),AOF 文件会被重写为一个空文件,届时将彻底回天乏术。
请按照以下步骤进行紧急恢复:
第一步:立刻停止 Redis 服务(防止 AOF 重写)
千万不要使用 redis-cli shutdown(因为它可能会触发保存)。建议直接在服务器上 kill 掉 Redis 进程:
# 找到 Redis 进程 ID
ps -ef | grep redis
# 优雅地 kill 掉进程(不要用 -9,除非 -15 杀不掉)
kill -15 <redis-pid>
第二步:立即备份 AOF 文件(核心救命步骤)
在进行任何修改之前,必须先备份现有的 AOF 文件。这是你最后的数据底线。
- 找到 Redis 的数据目录(通常在
redis.conf中的dir配置项下,默认为/var/lib/redis或当前目录)。 - 备份 AOF 文件:
对于 Redis 7.0 之前的版本(单 AOF 文件):
cp appendonly.aof appendonly.aof.bak
对于 Redis 7.0 及之后的版本(多部分 AOF - Multi-part AOF):
Redis 7.0 之后 AOF 被拆分为一个目录(通常叫 appendonlydir),里面有基础文件(.base.)和增量文件(.incr.)。
cp -r appendonlydir appendonlydir.bak
第三步:编辑 AOF 文件,剔除 FLUSHALL 命令
AOF 文件以 Redis 序列化协议(RESP)纯文本格式记录命令。由于 FLUSHALL 是刚误执行的,它一定在文件的最末尾。
操作步骤:
使用
vim或nano打开 AOF 文件。- Redis < 7.0:
vim appendonly.aof - Redis >= 7.0: 进入
appendonlydir目录,打开最新的增量文件(例如vim appendonly.aof.1.incr.aof)。
- Redis < 7.0:
在 vim 中按
Shift + G跳转到文件最后一行。你会看到类似如下格式的文本内容(这就是
FLUSHALL在 AOF 中的样子):plaintext*1 $8 flushall(注:如果是
FLUSHDB则为$7和flushdb;如果是异步清空FLUSHALL ASYNC,则结构会是*2开头包含async)删除这几行! 将关于
FLUSHALL的这几行(从*1开始到flushall结束)全部删除。保存并退出 (
:wq)。
第四步:使用修复后的 AOF 文件启动 Redis
- 确保你的
redis.conf中开启了 AOF(appendonly yes)。 - 启动 Redis 服务:bash
# 使用 systemctl 或者直接指定配置启动 systemctl start redis # 或者 ./redis-server /path/to/redis.conf - 查看 Redis 日志(
tail -f /var/log/redis/redis.log),你应该能看到 Redis 正在加载 AOF 文件到内存中:* DB loaded from append only file...
第五步:验证数据
使用 redis-cli 连接上去,执行以下命令确认数据是否回来:
redis-cli
127.0.0.1:6379> DBSIZE
127.0.0.1:6379> INFO keyspace
如果能看到 key 的数量恢复正常,恭喜你,抢救成功!
🚨 致命情况说明(什么情况下用此法无法恢复?)
如果你在误执行 FLUSHALL 后,Redis 碰巧执行了 BGREWRITEAOF(AOF 重写机制),旧的 AOF 文件会被一个体现当前内存状态(空库)的新 AOF 文件替换。
如果发生这种情况,AOF 抢救法将失效。 你只能去寻找昨天的 RDB 备份文件,或者云厂商提供的磁盘快照进行恢复。
亡羊补牢:如何防止此类事故再次发生?
事故处理完毕后,强烈建议立即在生产环境落实以下预防措施:
1. 禁用或重命名高危命令(最简单有效)
在 redis.conf 中加入以下配置,让这些命令失效或改成只有你知道的暗号:
rename-command FLUSHALL ""
rename-command FLUSHDB ""
rename-command KEYS ""
# 如果你想改名而不是禁用:
# rename-command FLUSHALL "FLUSHALL_DANGEROUS_999"
2. 启用 ACL 权限控制(Redis 6.0+)
为业务应用分配普通用户权限,只允许执行读写命令,禁止管理员命令。
3. 做好异地备份
编写 Shell 脚本结合 crontab,每天定时把 RDB 和 AOF 文件打包同步到 S3、OSS 或其他备份服务器上。