Lua 脚本之后,我们来看 Redis 如何把内存中的数据落到磁盘,以便在重启或故障后恢复。Redis 是内存型存储,默认数据只存在内存中;若不做持久化,进程退出或宕机后数据会丢失。 Redis 提供两种持久化方式:RDB(快照)与 AOF(追加写日志),二者在「恢复速度」「数据安全」「空间与性能」上各有取舍。
我们先从 RDB 与 AOF 的原理说起,再谈数据安全与性能的取舍,帮助你在生产环境中正确配置持久化。
RDB(Redis Database)是快照式持久化:在某一时刻将内存中的全部数据序列化到磁盘,生成一个二进制快照文件(默认 dump.rdb)。恢复时只需加载该文件即可,速度快、文件紧凑。RDB 的触发方式可以是手动(SAVE 或 BGSAVE)或定时(在配置中设置 save 900 1 等规则,满足「N 秒内至少 M 次写」则触发 BGSAVE)。SAVE 会阻塞主线程直到快照完成,生产环境通常用 BGSAVE:fork 子进程,由子进程写快照,主进程继续服务,期间新写入的数据通过写时复制(COW)与子进程共享,不影响一致性。
RDB 的缺点是两次快照之间的写入会丢失:若在 T1 做了快照、T2 宕机,则 T1 到 T2 之间的数据无法恢复。因此 RDB 适合「允许丢失分钟级数据」的缓存或会话场景,或作为 AOF 的补充(混合持久化中,AOF 重写时会先写一份 RDB 格式的存量数据)。RDB 的优点是恢复快、文件小、对主线程影响小(BGSAVE 时主线程只负责 fork 与 COW),适合做冷备或灾备的起点。
|BGSAVE CONFIG GET save

AOF(Append Only File)是日志式持久化:将每条写命令追加到 AOF 文件,重启时重放日志即可恢复数据。AOF 的数据安全性由刷盘策略决定:appendfsync always 表示每次写命令都同步落盘,数据最安全但性能最差;appendfsync everysec 表示每秒同步一次,最多丢一秒数据,性能与安全折中,是生产环境常用配置;appendfsync no 表示由操作系统决定何时刷盘,性能最好但可能丢较多数据。
AOF 的缺点是文件体积大、恢复慢:每条写命令都记录,文件会持续增长;恢复时需要逐条重放,数据量大时耗时长。Redis 提供了 AOF 重写(BGREWRITEAOF):由子进程根据当前内存数据生成一份新的 AOF,重写期间新命令写入重写缓冲区,重写完成后追加到新 AOF,再替换旧文件。这样既压缩了体积,又保证了数据完整。Redis 4.0+ 支持 RDB+AOF 混合持久化:AOF 重写时先用 RDB 格式写存量数据,再追加增量 AOF,恢复时先加载 RDB 再重放 AOF,兼顾恢复速度与数据安全。
|appendonly yes appendfsync everysec aof-use-rdb-preamble yes

持久化的本质是在「数据安全」与「性能/空间」之间做权衡。RDB 恢复快、空间小,但可能丢分钟级数据;AOF 可做到秒级甚至零丢失,但文件大、恢复慢。生产环境中,若数据可丢(纯缓存),可仅开 RDB 或关闭持久化;若数据重要(会话、分布式锁、有状态数据),建议开启 AOF,并选用 everysec;若既要恢复快又要少丢数据,可开启混合持久化(RDB 前缀 + AOF 增量)。
还需注意 fork 与内存:RDB 与 AOF 重写都会 fork 子进程,在数据量大时 fork 可能耗时较长,且子进程会短暂占用与主进程相当的内存(COW 前),因此需预留足够内存。在下一讲中,我们将看 Redis 的高可用与扩展:主从复制、Sentinel 与 Cluster 模式,届时会讨论如何在不丢数据的前提下实现故障转移与水平扩展。
