把内存治理讲清以后,下一步就该单独回答另一个问题:Redis 里的数据故障后要怎么回来。这篇只讲持久化与恢复,不再混入 TTL、淘汰和碎片率。

系列导航:

持久化先回答恢复目标,不要先背参数

讨论 Redis 持久化时,最容易犯的错是先问“该不该开 AOF”,却没有先回答两个更关键的问题:

  • 业务最多能接受丢多少数据,也就是 RPO
  • 业务最多能接受多久恢复,也就是 RTO

如果这两个目标不清楚,后面的 saveappendonlyappendfsync 往往只是照抄模板。因为 Redis 的持久化从来不是“开了就安全”,而是“你愿意为多小的丢失窗口和多快的恢复速度付出多少写入、磁盘和运维成本”。

一个最常见的判断框架是:

  • 纯缓存:重点是尽快恢复服务,通常不需要为非常严格的 RPO 付出高成本。
  • 可重建状态:可以接受一定丢失,但恢复过程不能太慢。
  • 关键在线状态:既希望少丢,又要求恢复快,就必须把持久化、复制和演练一起设计。

RDB 解决“某个时间点的整体快照”

RDB 的语义很直接:在某个时间点把当前数据集压成一份快照文件。它特别适合三类事情:

  • 周期性备份。
  • 重启后快速装载一份完整数据集。
  • 为复制初始化、迁移或离线分析提供基线数据。

如果主库需要向一个新副本做全量同步,底层也是先准备一份当下数据集的快照,再把快照后的增量写命令补过去。也正因为如此,RDB 的优点和代价都很明确:

  • 优点是文件紧凑、恢复通常更快。
  • 代价是两次快照之间的写入天然存在丢失窗口。

例如:

save 900 1
save 300 10
save 60 10000

这类配置表达的是“满足这些写入条件时,就生成一份新快照”。它不是持续日志,所以你不能指望 RDB 把最后一秒内的所有写入都精确保住。

AOF 解决“把写路径连续记录下来”

AOF 的思路不同。它不是保存一个静态瞬间,而是把写命令按顺序追加下来,让 Redis 在恢复时通过重放这些命令尽量逼近故障前的状态。

最常见的生产起点通常像这样:

appendonly yes
appendfsync everysec

这里最关键的是 appendfsync

  • always:每次写命令都刷盘,安全性最保守,但写入代价最高。
  • everysec:通常每秒刷盘一次,是很多生产环境的现实折中。
  • no:刷盘完全交给操作系统,性能开销更低,但丢失窗口更难控制。

AOF 的核心价值在于把 RPO 压得更细,但代价也很直接:

  • 写路径会承受额外 I/O。
  • 文件会持续增长。
  • 恢复速度会受到日志体积影响。

所以 AOF 不是“绝对优于 RDB”,而是“在你关心更小数据丢失窗口时,更有价值”。

混合持久化解决“既要恢复快,又不想日志无限膨胀”

如果只开 RDB,恢复窗口比较粗;如果只依赖 AOF,文件会长期膨胀,恢复也可能越来越慢。混合持久化的意义,就是把两种能力拼在一起。

Redis 常见的做法是开启 AOF,同时让重写后的 AOF 前半段以 RDB preamble 的方式保存一份紧凑快照,再在后面接上最近的增量写命令。常见配置形态类似:

appendonly yes
appendfsync everysec
aof-use-rdb-preamble yes

你可以把它理解成:

  • 基线数据用快照方式保存,装载更快。
  • 最近增量继续用 AOF 命令补齐,丢失窗口更小。
  • AOF 重写负责把越来越长的历史命令重新收敛成“恢复当前状态真正需要的内容”。

这也是很多生产环境最终采用的组合路径:不是在 RDBAOF 之间二选一,而是把它们放进同一套恢复设计里。

恢复目标会反过来决定你的持久化组合

RPORTO 放回来看,很多配置选择就不再抽象:

  • 如果 RPO 很宽松,纯缓存实例可能只保留轻量快照,甚至更依赖重建而非持久化。
  • 如果 RPO 很严格,就不能只靠间隔较长的 RDB,通常要引入 AOF 或混合持久化。
  • 如果 RTO 很严格,你就不能只想着“尽量少丢”,还得控制恢复时要回放的日志规模,并实际演练恢复耗时。

真正决定配置的,不是“Redis 推荐开哪个”,而是“业务愿意接受什么损失、团队能承受什么写入开销、故障时是否有明确恢复流程”。

恢复不是配置项,而是一条演练过的路径

很多团队把持久化做成了“配置存在”,却没有把恢复做成“流程存在”。真正上线前至少要确认:

  1. 故障后优先从哪份数据恢复,是 RDBAOF 还是重建。
  2. AOF 文件规模是否长期可控,重写是否在正常发生。
  3. 恢复后的数据校验怎么做,哪些业务指标说明服务真的回来了。
  4. 备份文件是否可获取、可校验、可在隔离环境实际加载。

如果这些问题没有演练过,那么“我已经开启持久化”在故障当天的价值其实很有限。

一套够用的持久化选型起点

如果你需要一个足够实用的起点,可以先按下面方式判断:

  • 纯缓存:先想清楚是否真的需要恢复 Redis 本身,而不是直接由上游重建。
  • 一般在线状态:保留 RDB 基线,同时结合 AOF everysec 或混合持久化,通常更平衡。
  • 恢复要求更高:把 AOF、重写频率、磁盘能力、备份保留和恢复演练一起纳入方案,而不是只调一个参数。

记住一个最重要的原则:持久化的目标不是“让 Redis 看起来更像数据库”,而是让你在故障发生后,能以可接受的数据损失和时间成本把服务真正恢复回来。

本篇解决了什么:

  • 说明了为什么讨论持久化前要先明确 RPORTO
  • 拆清了 RDBAOF、混合持久化和恢复演练各自负责什么
  • 把持久化选择从“抄配置模板”拉回到真实恢复目标

下一篇:Redis 主从复制与 Sentinel:从复制链路到自动故障切换(九)