Redis 是内存数据库,但数据不能只放在内存里——断电即失。持久化(persistence)是 Redis 绕不开的话题:RDB(快照)与 AOF(追加日志)是两条互补的路线,前者恢复快但可能丢最近的数据,后者丢得少但文件大恢复慢。生产环境几乎都是两者混合,而混合持久化的设计(Redis 4.0+)本身就是对两者优劣的最好总结。本篇讲清两者的机制、取舍与选型框架。

RDB:某一刻的完整快照
RDB(Redis Database)的机制:将某个时刻的全部数据以紧凑的二进制格式写入磁盘。触发方式两种:手动触发(SAVE 阻塞主线程 / BGSAVE fork 子进程后台执行);自动触发(配置 save 规则,如「900 秒内至少 1 次修改则触发」)。
BGSAVE 的实现依赖操作系统的 fork:主进程 fork 出一个子进程,子进程共享父进程的内存页(写时复制 CoW——本库 OS 系列详述),子进程遍历内存生成 RDB 文件,父进程继续服务请求。fork 的代价与内存大小成正比(内存越大,页表越大,fork 越慢),CoW 的代价与写入量成正比(父进程在 BGSAVE 期间的写入会触发页复制,内存占用可能翻倍)。
RDB 的优势:文件紧凑(二进制全量快照),恢复速度极快(直接加载到内存);适合备份与灾难恢复。劣势:两次快照之间的数据在宕机时全部丢失——如果 save 间隔是 5 分钟,最坏丢 5 分钟的数据;对缓存场景可以接受(重新从 DB 加载),对「Redis 当数据库用」的场景不可接受。
AOF:每个写操作都记日志
AOF(Append Only File)的机制:将每个写命令追加到日志文件——类似数据库的 WAL(Write-Ahead Log,本库语境的「先记日志再执行」),重启时重放日志恢复状态。AOF 的写入策略由 appendfsync 参数控制:always——每个命令都 fsync,最安全最慢;everysec——每秒 fsync 一次(默认),最多丢 1 秒的数据;no——由操作系统决定何时 fsync,最快但最不安全。
AOF 重写(rewrite)解决日志膨胀问题:AOF 记录的是「操作历史」,同一个 key 可能被写了一百次——重写操作根据当前内存状态生成一份「最终等价」的最小命令集,用新文件替换旧文件。重写也是 fork 子进程执行(与 BGSAVE 相同的 CoW 机制)。
AOF 的优势:数据丢失窗口小(everysec 最多丢 1 秒),日志可读(文本格式的 Redis 命令)。劣势:文件比 RDB 大得多(记录了所有操作历史),恢复速度慢(要重放所有命令),对同一 key 的多次操作产生大量冗余日志(重写可以缓解但增加系统复杂度)。
混合持久化:取两者之长
Redis 4.0 引入混合持久化(hybrid persistence)——AOF 重写时,先以 RDB 格式写入当前全量数据,再追加增量 AOF 命令。重启恢复时:先加载 RDB 部分(快速恢复绝大部分数据),再重放少量增量 AOF 命令(恢复最近的数据)——兼得 RDB 的恢复速度与 AOF 的低丢失。
flowchart LR
A["数据写入"] --> B{"持久化策略"}
B --> C["RDB<br>定期快照<br>恢复快 · 可能丢数据"]
B --> D["AOF<br>追加日志<br>丢得少 · 恢复慢"]
B --> E["混合(推荐)<br>RDB 全量 + AOF 增量<br>恢复快 + 丢得少"]
C --> F["重启"]
D --> F
E --> F
选型框架:按场景选持久化策略
纯缓存场景(数据可从 DB 重建):可以只开 RDB(或甚至关闭持久化——重启后从 DB 加载),持久化的意义仅是「避免冷启动的缓存雪崩」。缓存 + 少量持久数据(如分布式锁的租约):RDB + AOF(everysec),丢 1 秒的锁租约可通过锁的超时机制兜底。Redis 当主数据库用:必须开 AOF(everysec 或 always)+ 定期 RDB 备份 + 主从复制——三层保护缺一不可。资源极度受限(内存只够数据用,fork 可能 OOM):只开 AOF(避免 BGSAVE 的 CoW 内存翻倍风险)。
RDB 文件结构与混合持久化的文件格式
RDB 文件是紧凑的二进制文件(通常几 MB 到几十 MB),内部结构包含文件头(REDIS 魔数加版本号)、辅助字段(Redis 版本、创建时间、内存使用量)、以及数据库的键值对数据。恢复过程:Redis 启动时检测到 RDB 文件,直接将二进制数据反序列化到内存——恢复速度取决于文件大小与内存分配速度。AOF 的文件结构则是文本格式(RESP 协议的 Redis 命令序列),每条命令一行——可读性好但体积大。混合持久化的文件结构:AOF 重写时的文件前半部分是 RDB 格式(全量数据),后半部分是 AOF 格式(增量命令)——兼得两者的优点。文件压缩:RDB 支持 LZF 压缩(默认开启)——字符串值压缩后存储,减少文件大小。理解文件结构有助于诊断持久化问题(如 RDB 文件损坏时的修复)。
无持久化的场景:什么时候可以关掉
一个反直觉的建议:某些场景下可以完全关闭 Redis 的持久化。纯缓存场景(数据完全可以从 DB 重建)——Redis 只是 DB 的加速层,数据丢失后从 DB 重新加载即可(虽然会有缓存雪崩的风险——需要预热策略配合)。使用 Redis 作为临时队列或锁(数据有时效性,过期自动清理——持久化没有意义)。纯计数器或限流器(数据是运行时状态,丢失后从零重新计数可以接受)。关闭持久化的方法:在配置文件中注释掉所有 save 行并禁用 appendonly——Redis 启动后不加载任何持久化文件。风险提示:关闭持久化后如果 Redis 重启,所有数据清零——对于缓存场景需要实现「启动预热」(从 DB 逐批加载数据到 Redis——避免同时的大量 DB 查询导致缓存雪崩)。
AOF 重写:解决日志膨胀的重写机制
AOF 记录的是操作历史,同一个 key 被写一百次就有一百条日志——文件持续膨胀。AOF 重写根据当前内存状态生成一份最小等价命令集:不重放旧日志,而是直接扫描当前内存中的每个 key,生成一条等价的写命令。例如某个 key 被写了一百次,重写后只有一条最终的 SET 命令。重写也是 fork 子进程执行(与 BGSAVE 相同的 CoW 机制),期间新写入的命令同时写入旧 AOF 与重写缓冲区,重写完成后原子替换旧文件。重写的触发可以是手动(BGREWRITEAOF 命令)或自动(当 AOF 文件大小超过上次重写后大小的指定百分比时自动触发)。重写期间的性能影响:fork 的开销与 CoW 的内存增长(与 RDB 相同),但重写本身只写少量数据(当前状态的等价命令远少于历史操作),所以重写速度通常比 RDB 更快。
Redis 主从复制与哨兵模式:持久化之外的高可用
持久化解决的是单机的数据安全,主从复制解决的是单点的可用性。主从复制:主节点的写操作同步到从节点(从节点只读),主节点宕机时从节点晋升为新主。哨兵模式:独立的哨兵进程监控主节点的健康状态——主节点不可用时自动执行故障转移(从节点中选出一个晋升为新主,通知客户端新的主节点地址)。哨兵的选主逻辑按照优先级大于复制偏移量大于运行 ID 的顺序选出新主。主从复制的缺点:主节点的写入能力是瓶颈且复制是异步的(主节点宕机时从节点可能缺少最新的写入)。Redis Cluster 解决了写入的扩展性(16384 个 slot 分片到多个主节点),但引入了新的复杂度(多 key 操作受限、客户端路由)。
持久化的监控与运维
Redis 持久化的监控与运维有关键指标与排查方法。RDB 的监控:last_bgsave_status(最近一次 BGSAVE 的状态)、rdb_last_bgsave_time_sec(BGSAVE 耗时)——BGSAVE 失败的常见原因是 fork 失败(内存不足)或磁盘空间不足。AOF 的监控:aof_enabled(是否开启)、aof_last_bgrewrite_status(最近一次重写的状态)、aof_current_size(当前 AOF 文件大小)——AOF 文件大小持续增长说明需要重写。AOF 恢复的排查:redis-check-aof 工具可以检查 AOF 文件的完整性。持久化的故障排查还有一个通用方法:查看 Redis 的 INFO persistence 命令输出——包含所有持久化相关的状态信息。
混合持久化的配置与运维
混合持久化的配置需要设置 aof-use-rdb-preamble = yes。运维方面的关键指标包括 rdb_last_bgsave_status(最近一次 BGSAVE 的状态)、aof_last_bgrewrite_status(最近一次重写的状态)、aof_current_size(当前 AOF 文件大小)与 aof_base_size(上次重写后的大小)。AOF 文件大小持续增长说明需要重写。AOF 恢复的排查工具是 redis-check-aof 可以检查 AOF 文件的完整性。持久化的故障排查通用方法:查看 INFO persistence 命令输出。
Redis 持久化的选型决策树与生产实践
Redis 持久化的选型按场景决策:纯缓存场景可以只开 RDB 甚至关闭持久化因为数据可以从 DB 重建但需要启动预热策略避免缓存雪崩。缓存加少量持久数据如分布式锁的租约需要 RDB 加 AOF everysec 丢一秒的锁租约可以通过锁的超时机制兜底。Redis 当主数据库用必须开 AOF everysec 或 always 加定期 RDB 备份加主从复制三层保护缺一不可。资源极度受限内存只够数据用时只开 AOF 避免 BGSAVE 的 CoW 内存翻倍风险。生产环境的最佳实践是开启混合持久化加定期 RDB 备份加主从复制。持久化的监控指标有 rdb_last_bgsave_status 和 aof_last_bgrewrite_status 和 aof_current_size。
小结
Redis 持久化收成四条:RDB 是快照——文件小恢复快,但两次快照间的数据在宕机时全丢,BGSAVE 的 fork 依赖 CoW(内存大时 fork 慢、写入多时内存翻倍);AOF 是日志——每秒 fsync 最多丢 1 秒,但文件大恢复慢,重写机制解决膨胀但增加复杂度;混合持久化取两者之长——重写时先写 RDB 再追加增量 AOF,兼得恢复速度与低丢失;选型按场景——纯缓存可只开 RDB,当数据库用必须三层保护(AOF + RDB + 主从复制)。持久化的选择没有对错,只有「你愿意为数据安全支付多少性能代价」的权衡。
参考资料
- Redis 官方文档:Persistence —— RDB 与 AOF 的权威说明
- 本库前篇:《缓存一致性实战》《操作系统内功 · 第 4 篇|文件系统与 Page Cache》
读者留言
COMMENTS 暂无还没有留言,来说第一句?