Redis 误操作数据恢复
误操作的常见场景
在生产环境中,Redis 误操作可能发生在多个环节:
| 误操作类型 | 示例 | 后果 |
|---|---|---|
| 误删 key | DEL important_key |
关键数据丢失 |
| 误删库 | FLUSHDB / FLUSHALL |
当前/所有数据库清空 |
| 误覆盖 | SET key wrong_value |
正确数据被覆盖 |
| 误过期 | EXPIRE key 0 / 设错 TTL |
key 被立即/提前删除 |
| 误替换 | 误替换了数据结构 | List/Hash/Set 数据被覆盖 |
恢复策略概览
误操作发生
↓
判断操作类型
├── 数据被删(DEL/FLUSH)
│ ├── AOF 仍保留命令?→ 从 AOF 恢复
│ ├── 有 RDB 快照?→ 回到快照时间点
│ └── 有备份?→ 从备份恢复
│
├── 数据被覆盖(SET/HSET)
│ ├── AOF 有记录?→ 可以精确恢复
│ └── 无记录?→ 只能回滚到备份点
│
└── 大量数据丢失
├── 从备份 RDB 恢复到新实例
└── 使用 diff 工具找出差异数据
方法一:AOF 日志恢复(最精确)
原理
如果开启了 AOF,所有写操作都以 Redis 协议格式记录在 AOF 文件中。可以通过编辑 AOF 文件,删除误操作的命令,然后重放。
恢复流程
# 场景:误执行了 FLUSHALL
# Step 1: 立即停止 Redis 避免数据被覆盖
redis-cli SHUTDOWN NOSAVE
# Step 2: 备份当前的 AOF 文件
cp /var/lib/redis/appendonly.aof /backup/appendonly_before_flush.aof
# Step 3: 从 AOF 中删除 FLUSHALL 命令
# FLUSHALL 在 AOF 中的记录
*1
$8
FLUSHALL
# 使用工具移除
redis-check-aof --fix-remove-cmd "FLUSHALL" appendonly.aof
# 或者手动编辑:
grep -v "FLUSHALL" appendonly.aof > appendonly_clean.aof
注意:AOF 重写后 FLUSHALL 命令就不在了(被合并到新的基础快照中)。所以误操作后要立即处理。
恢复单条 DEL 命令
# 场景:误 DEL 了某个关键 key
# Step 1: 停止 Redis,备份 AOF
redis-cli SHUTDOWN
cp appendonly.aof appendonly.aof.bak
# Step 2: 在 AOF 中找到误操作的命令
# AOF 记录格式(协议文本模式):
*1
$3
DEL
$5
mykey
# Step 3: 删除该命令,可以精准恢复
# 使用 Python 脚本
python3 << 'EOF'
import re
aof_file = "/var/lib/redis/appendonly.aof"
target_cmd = b"*1\n$3\nDEL\n$5\nmykey\n"
with open(aof_file, "rb") as f:
content = f.read()
# 删除目标命令
new_content = content.replace(target_cmd, b"")
with open(aof_file + ".fixed", "wb") as f:
f.write(new_content)
print(f"原始大小: {len(content)} bytes")
print(f"修复后大小: {len(new_content)} bytes")
print(f"AOF 修复完成: {aof_file}.fixed")
EOF
方法二:RDB 快照恢复
恢复到快照时间点
# 场景:误操作 30 分钟,最近一次 RDB 快照是 1 小时前
# Step 1: 使用 RDB 备份恢复到新实例
redis-server --port 6380 --dbfilename dump_backup.rdb \
--dir /tmp --daemonize yes
# Step 2: 比较数据差异
# 导出原始数据
redis-cli -p 6379 KEYS "*" > /tmp/keys_current.txt
redis-cli -p 6380 KEYS "*" > /tmp/keys_backup.txt
# 找出丢失的 key
diff /tmp/keys_current.txt /tmp/keys_backup.txt | grep "^>" | cut -d' ' -f2 > /tmp/missing_keys.txt
# Step 3: 从备份实例逐个恢复丢失的 key
cat /tmp/missing_keys.txt | while read key; do
type=$(redis-cli -p 6380 TYPE "$key")
case $type in
string)
val=$(redis-cli -p 6380 GET "$key")
redis-cli -p 6379 SET "$key" "$val"
;;
hash)
redis-cli -p 6380 HGETALL "$key" | xargs redis-cli -p 6379 HMSET "$key"
;;
list)
redis-cli -p 6380 LRANGE "$key" 0 -1 | tac | sed '1~2d' | xargs -I {} redis-cli -p 6379 RPUSH "$key" {}
;;
set)
redis-cli -p 6380 SMEMBERS "$key" | xargs redis-cli -p 6379 SADD "$key"
;;
zset)
redis-cli -p 6380 ZRANGE "$key" 0 -1 WITHSCORES | xargs redis-cli -p 6379 ZADD "$key"
;;
esac
echo "已恢复: $key"
done
方法三:利用主从复制恢复
如果误操作时主从架构运转正常:
# 场景:在主库误操作,从库还未同步
# Step 1: 立即在从库执行 SLAVEOF NO ONE
redis-cli -p 6380 SLAVEOF NO ONE
# Step 2: 从从库导出被删除的数据(如果有)
# 注意:如果从库已经复制了误操作命令,此方法无效
# Step 3: 恢复主库
redis-cli -p 6380 BGSAVE # 从库生成快照
# 将 RDB 文件传到主库
# 重启主库加载该 RDB
预防误操作的最佳实践
1. 使用 RENAME 重命名危险命令
# redis.conf
rename-command FLUSHALL ""
rename-command FLUSHDB ""
rename-command DEL "safe_del"
rename-command KEYS "safe_keys"
2. 设置操作确认(通过 Lua 脚本)
-- 实现一个"安全 DEL",需要二次确认
local key = KEYS[1]
local confirm = ARGV[1]
if confirm ~= "YES_I_AM_SURE" then
return "ERROR: 请确认删除操作,使用 YES_I_AM_SURE 确认"
end
return redis.call("DEL", key)
3. 使用 Redis 6.0+ ACL 权限控制
# 创建只读用户(避免误操作)
redis-cli ACL SETUSER readonly_user on >password +@read ~*
# 创建有写权限但无危险命令的用户
redis-cli ACL SETUSER normal_user on >password +@write -@dangerous ~*
# 普通开发人员使用 readonly_user
4. 延迟执行的”回收站”机制
-- 带回收站的删除
local key = KEYS[1]
local ttl = tonumber(ARGV[1]) or 86400 -- 默认保留1天
-- 重命名 key 并设置过期(相当于移到回收站)
local trash_key = "trash:" .. key
redis.call("RENAME", key, trash_key)
redis.call("EXPIRE", trash_key, ttl)
return 1
恢复速查表
| 误操作 | 恢复方法 | 恢复精度 | 恢复时间 |
|---|---|---|---|
| DEL 单个 key | AOF 移除 DEL 命令 | 秒级 | 分钟级 |
| FLUSHALL | AOF 移除 FLUSHALL | 秒级 | 分钟级 |
| SET 覆盖值 | AOF 中删除 SET | 秒级 | 分钟级 |
| 批量 DEL | RDB 恢复 + diff | 小时级 | 分钟级 |
| 无备份误删 | 无法恢复 | — | — |
| 过期 key | 无法恢复 | — | — |
面试要点
- 黄金第一原则:误操作后立即停止 Redis(或停写操作)
- AOF 是救命稻草:只要没执行 BGREWRITEAOF,AOF 还保留着命令
- RDB 兜底:即使 AOF 不可用,RDB 快照是最后的防线
- 预防>恢复:RENAME 危险命令、使用 ACL、定期备份
- TTL 数据不可恢复:过期 key 一旦删除无法通过 AOF 恢复
- 主从方案:误操作后立即 SLAVEOF NO ONE 隔离从库
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END


暂无评论内容