Redis 持久化管理:RDB 与 AOF 配置、备份与恢复实战
Redis 是内存数据库,进程退出或机器宕机后内存数据全部消失,能否恢复、恢复多少,全看持久化配置。线上最常见的事故不是 Redis 挂了,而是重启之后发现丢了几分钟甚至几小时的数据:有人只开了 RDB 且快照间隔太长,有人 AOF 文件损坏又没做校验。本文系统梳理 RDB 与 AOF 的配置、备份、恢复与校验修复流程,适用于单机、主从架构下负责数据落盘的 Redis 7.x 实例。
前置条件
- Redis 7.x 已安装并可正常启动,示例主机名为 redis-01,数据目录为 /data/redis
- 有 redis.conf 的修改权限,修改后可重启或执行 CONFIG SET 热更新
- 磁盘空间至少为数据集内存占用的 2.5 倍(快照与 AOF 重写期间新旧文件并存)
RDB 快照:配置与原理
RDB 是把整个数据集在某一时刻序列化成紧凑的二进制文件。触发方式有手动执行 SAVE / BGSAVE,或用 save 指令配置自动快照点:格式为「秒数 变更键数」,即在指定秒数内至少发生指定次数的写操作就触发一次 BGSAVE,可以写多行叠加。
# redis.conf:RDB 相关核心配置
dir /data/redis
dbfilename dump.rdb
save 3600 1
save 300 100
save 60 10000
stop-writes-on-bgsave-error yes
BGSAVE 的原理是主进程 fork 出子进程,由子进程把数据写到临时 RDB 文件,写完后原子替换旧文件。fork 依赖操作系统的写时复制(copy-on-write):父子进程最初共享同一批内存页,父进程处理写请求时才复制被修改的页。风险也在这里:快照期间写入越活跃,被复制的页越多,极端情况下内存占用接近翻倍。因此实例内存不要超过物理内存的一半,并务必关闭透明大页(THP),否则单页复制粒度变大、延迟毛刺明显。stop-writes-on-bgsave-error 设为 yes 可在快照失败时拒绝写入,避免「以为在备份、其实早已失败」的静默丢数据。
手动触发有 SAVE 与 BGSAVE 两个命令:SAVE 由主进程亲自写文件,期间阻塞所有客户端请求,生产环境禁用;BGSAVE 走 fork 子进程,是唯一正确的手动方式。另有两个细节建议保持默认:rdbchecksum yes 会在 RDB 尾部写入 CRC64 校验和,加载时自动验完整性,仅损失少量性能;rdbcompression yes 用 LZF 压缩字符串,能明显减小文件,代价是快照时多耗一些 CPU。
AOF 日志:同步策略与重写
AOF 以追加方式记录每条写命令,重启时按序重放即可恢复数据。是否丢数据取决于 appendfsync 的刷盘策略:
- always:每条命令都 fsync,最多丢一条命令,性能损失最大,一般只用于极端敏感场景
- everysec:每秒 fsync 一次,宕机最多丢 1 秒数据,是官方推荐值,绝大多数业务选它
- no:完全交给操作系统刷盘,Linux 默认最长约 30 秒才落盘,宕机丢数据窗口最大
# redis.conf:AOF 相关核心配置
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
还有一个取舍项 no-appendfsync-on-rewrite:设为 yes 时,重写期间主进程不再 fsync AOF,避免与子进程抢磁盘导致延迟飙升,但代价是这段时间宕机可能多丢约 30 秒数据;磁盘 IO 宽裕时保持 no,更在意延迟抖动的大实例可以设 yes,但要清楚自己在拿数据安全换延迟。
AOF 只追加不删除会无限膨胀,靠重写(BGREWRITEAOF)把当前数据集压缩成最少命令集。
自动重写触发条件是同时满足两条:当前 AOF 文件大小比上次重写后增长超过 auto-aof-rewrite-percentage(默认 100%,即翻倍),且文件不小于 auto-aof-rewrite-min-size(默认 64mb)。重写同样走 fork 子进程,大实例上要留意内存与磁盘 IO,可在业务低峰用 BGREWRITEAOF 手动触发分摊压力。Redis 7 多段 AOF 与混合持久化
Redis 7 把 AOF 改为多段(Multi-Part AOF)结构:appendonlydir 目录下由一个 manifest 清单文件管理多个文件——历史全量部分是 base 文件(本质就是 RDB 格式),之后是若干 incr 增量文件记录新写命令。重写时生成新 base 与新 incr,再更新 manifest 切换,旧文件随之删除,解决了老版本重写期间文件替换的边界问题。混合持久化由 aof-use-rdb-preamble 控制(默认 yes):开启后,与多段 AOF 的 base 部分同理,重写生成的全量段以 RDB 格式存储,后面再追加增量命令。好处是加载时先按二进制快速读大头、再重放少量命令,恢复速度大幅提升,文件体积也比纯文本 AOF 小。生产环境保持默认开启即可。
备份策略:定时拉取加异地留存
持久化文件在本机只能防进程重启,防不了磁盘损坏和误删除,必须定时拉取到异地。推荐做法:凌晨低峰触发 BGSAVE,按完成时间把 dump.rdb 拉到备份机并按日期归档,保留 7 天;AOF 目录同步增量拉取一份。
# 手动触发快照并等待完成(rdb_last_bgsave_time_sec 变化即完成)
redis-cli -h 127.0.0.1 BGSAVE
redis-cli -h 127.0.0.1 INFO persistence | grep -E 'rdb_last_bgsave'
# 拉取到备份机按日期留存(示例备份机 192.0.2.20)
scp redis-01:/data/redis/dump.rdb \
backup@192.0.2.20:/backup/redis/dump-$(date +%F).rdb
归档环节再加两条纪律:拉取完成后立刻对备份文件做一次校验(方法见后文),校验不过就告警而不是默默留存;保留策略建议按天留 7 份、按周再留 4 份,因为数据损坏或误删除往往不是当天发现的,只留最新一份等于没有回退空间。备份目录权限也要收紧,RDB 与 AOF 里就是全量业务数据,按数据文件同等级别保护。
从备份恢复:完整步骤
恢复前先明确规则:只要开启了 AOF,Redis 启动时优先加载 AOF(7.x 读 appendonlydir 的 manifest),忽略同目录的 RDB。所以想用 RDB 恢复必须先关掉 AOF;用 AOF 恢复则保证 appendonlydir 内容完整。
# 场景一:用 RDB 恢复
systemctl stop redis
cp /backup/redis/dump-2026-11-08.rdb /data/redis/dump.rdb
chown redis:redis /data/redis/dump.rdb
# 确认 redis.conf 中 appendonly 为 no 后再启动
systemctl start redis
# 场景二:用 AOF 恢复,把整个目录拷回
systemctl stop redis
rsync -a /backup/redis/appendonlydir/ /data/redis/appendonlydir/
chown -R redis:redis /data/redis/appendonlydir
# 确认 appendonly 为 yes 后启动
systemctl start redis
# 启动后核对数据量
redis-cli INFO keyspace
文件校验与 AOF 损坏修复
备份拉下来先用官方工具校验再归档,避免留存一堆坏文件。RDB 用 redis-check-rdb,退出码为 0 且结尾显示校验通过才算完好;AOF 用 redis-check-aof,它会逐条解析命令检查完整性。
redis-check-rdb /data/redis/dump.rdb
redis-check-aof /data/redis/appendonlydir/*.aof*
若 AOF 尾部因断电写入一半而损坏,redis-check-aof --fix 可以截断到最后一条完整命令的位置。但必须注意:7.x 的多段 AOF 修复是按 manifest 中登记的文件逐段处理的,且修复等于直接丢弃损坏点之后的所有数据,执行前先整目录备份、确认丢弃范围可接受;若损坏发生在中间位置,通常只能截断其后全部数据,损失可能远超预期,这也是为什么异地备份不能只留最新一份。
验证
改完配置后不要只看进程能启动,要逐项确认持久化真的在工作:写入一个带标记的键,执行 BGSAVE 后检查 RDB 文件时间戳已更新;重启实例,确认标记键还在且 DBSIZE 与重启前一致;再看 INFO persistence 中两个状态字段都为 ok,AOF 开启时 aof_enabled 为 1。
redis-cli SET persist_test ok
redis-cli BGSAVE
ls -l --time-style=full-iso /data/redis/dump.rdb
redis-cli INFO persistence | grep -E 'rdb_last_bgsave_status|aof_enabled|aof_last_bgrewrite_status|aof_last_write_status'
常见问题
fork 导致内存翻倍、甚至被 OOM Kill
BGSAVE / 重写期间写流量越大,写时复制的页越多。把单实例内存控制在物理内存 50% 以内,关闭透明大页,并用 INFO memory 的 mem_fragmentation_ratio 与系统可用内存持续监控。
磁盘被持久化文件打满
重写与快照期间新旧文件并存,加上自动重写失败反复重试极易撑爆磁盘。给 /data/redis 单独划盘或配额并做 80% 水位告警;stop-writes-on-bgsave-error 保持 yes,让故障表现为拒绝写入而不是悄悄丢弃备份能力。
只开 RDB 的丢数据窗口有多大
按默认 save 60 10000 配置,最坏情况下要丢两次快照之间近 1 小时的数据;如果写量达不到触发条件,窗口还会更长。有人误以为「开了持久化就万无一失」,实际上只有 RDB 或 appendfsync no 的组合,宕机后丢几分钟到几十分钟是常态。对数据有要求的业务,必须开 AOF 且 appendfsync everysec,把窗口压到 1 秒。
小结
持久化的稳妥组合是:RDB 做定时全量备份并异地留存,AOF 以 everysec 常开兜底日常宕机,混合持久化保持默认加速恢复;备份文件定期用 redis-check-rdb 与 redis-check-aof 校验,并真正演练一次恢复流程——备份的价值只在恢复成功的那一刻才成立。







