持久化
约 2038 字大约 7 分钟
2025-09-01
Redis 提供了两种主要的持久化机制:RDB(Redis Database Backup)和 AOF(Append Only File),以确保在 Redis 实例重启后数据不会丢失。在默认配置 redis.conf 中,RDB 是默认开启的,而 AOF 需要手动配置开启。
RDB
RDB 是 Redis DataBase Backup 的缩写,也被称为 Redis 数据快照。它通过将 Redis 在内存中的所有数据以二进制格式保存到磁盘文件中。当 Redis 实例故障重启后,可以通过加载 RDB 文件快速恢复数据。
触发机制
RDB 的触发机制分为自动触发和手动触发。
自动触发(
bgsave) 在redis.conf配置文件中,可以通过save配置项设置 RDB 的自动触发条件:save 900 1:在 900 秒(15 分钟)内,如果至少有 1 个 key 被修改,则执行bgsave命令。save 300 10:在 300 秒(5 分钟)内,如果至少有 10 个 key 被修改,则执行bgsave命令。save 60 10000:在 60 秒内,如果至少有 10000 个 key 被修改,则执行bgsave命令。
手动触发
SAVE命令:由 Redis 主进程执行 RDB 操作。在 RDB 期间,主进程会阻塞所有客户端命令,不建议在生产环境使用。BGSAVE命令:开启一个子进程执行 RDB 操作。主进程不会被阻塞,可以继续处理客户端请求。这是推荐的手动触发方式。
RDB 异步持久化的底层原理
BGSAVE 命令实现了 RDB 的异步持久化。其核心原理是利用操作系统的 fork() 系统调用创建子进程来执行持久化任务。
fork()过程:当执行BGSAVE命令时,Redis 主进程会调用fork()创建一个子进程。fork()操作会复制主进程的页表(Page Table),使子进程共享主进程的内存数据。这个fork()过程是阻塞的,Redis 主进程在此期间无法处理客户端请求。- 写时复制(Copy-On-Write, COW):为了避免主进程在写数据时与子进程读取数据造成冲突,Redis 利用了操作系统的 COW 机制。
- 在
fork()完成后,主进程和子进程会共享同一份内存数据,这些内存页被标记为只读。 - 当主进程需要修改(写)共享内存中的某个数据页时,操作系统会为这个数据页创建一个副本,主进程在副本上执行写操作。原始的数据页仍然保持不变,供子进程读取。
- 子进程在执行
BGSAVE期间,会读取共享内存(或未被主进程修改而触发 COW 的内存页)中的数据,并将其写入 RDB 文件。
- 在
优缺点
优点
- 恢复速度快:RDB 文件是一个压缩的二进制文件,加载速度比 AOF 快,适合用于灾难恢复。
- 文件体积小:RDB 文件存储的是数据的最终状态,不包含中间操作,因此文件体积相对较小。
缺点
- 数据安全性问题:RDB 是周期性执行的,两次 RDB 之间写入的数据如果 Redis 发生宕机,这部分数据将会丢失。RDB 的执行间隔不能设置过短,因为
fork()和写 RDB 文件本身是耗时操作。 fork()阻塞:fork()子进程的过程是阻塞的,如果实例内存较大,fork()操作可能会导致 Redis 在短时间内无法响应请求。
- 数据安全性问题:RDB 是周期性执行的,两次 RDB 之间写入的数据如果 Redis 发生宕机,这部分数据将会丢失。RDB 的执行间隔不能设置过短,因为
AOF
AOF(Append Only File)是一种“追加文件”持久化方式。它通过记录 Redis 处理的每一个写命令来持久化数据。AOF 文件可以被视为一个命令日志文件,当 Redis 重启时,会重新执行 AOF 文件中的命令来恢复数据。
AOF 刷盘策略
AOF 的刷盘频率可以通过 appendfsync 配置项来设置,这决定了数据写入 AOF 文件的安全性与性能之间的平衡:
always:同步刷盘。每个写命令执行后都会立即同步写入 AOF 文件并刷盘。数据安全性最高,但性能开销最大,因为每次写操作都会阻塞直到数据写入磁盘。everysec(默认):每秒刷盘。写命令先写入 AOF 缓冲区,然后每隔一秒将缓冲区数据写入 AOF 文件并刷盘。这是一个折中方案,性能较好,最多丢失 1 秒的数据。no:由操作系统控制。写命令写入 AOF 缓冲区后,由操作系统决定何时将缓冲区内容写入 AOF 文件。数据安全性最低,完全依赖操作系统,但性能最好。
AOF 文件重写
为了解决 AOF 文件体积过大和冗余命令的问题,Redis 提供了 AOF 文件重写(BGREWRITEAOF)功能。
AOF 重写会创建一个新的 AOF 文件,用最少的命令来达到相同的最终数据状态。例如,对于一个 key 的多次 INCR 操作,重写后可能只记录一个 SET 命令。
触发机制: AOF 重写可以通过
BGREWRITEAOF命令手动触发,也可以通过配置文件中的阈值自动触发:auto-aof-rewritemin-size:AOF 文件最小达到指定大小才会触发重写。auto-aof-rewrite-percentage:当前 AOF 文件大小比上次重写后文件大小增长的百分比达到指定值时触发重写。
重写原理: AOF 重写过程与 RDB 的
BGSAVE类似,也是通过fork()子进程来完成的。- 主进程
fork()一个子进程。 - 子进程遍历当前内存中的数据,将其转换为一系列写命令,写入到一个临时 AOF 文件中。
- 在子进程重写期间,主进程仍然正常处理客户端请求,并将新的写命令追加到旧的 AOF 文件和 AOF 重写缓冲区中。
- 当子进程完成重写后,主进程会将 AOF 重写缓冲区中的命令追加到新的 AOF 文件末尾。
- 最后,用新的 AOF 文件替换旧的 AOF 文件,完成重写。
- 主进程
优缺点
优点
- 数据安全性高:
everysec策略最多丢失 1 秒的数据,always策略几乎不丢失数据。 - 日志清晰:AOF 文件是文本格式,记录的是命令序列,易于理解和解析(在发生错误时进行调试)。
- 数据安全性高:
缺点
- 恢复速度慢:AOF 文件恢复时需要重新执行所有命令,如果文件较大,恢复时间会很长。
- 文件体积大:AOF 文件记录的是命令,通常比 RDB 文件大。
混合持久化
为了兼顾 RDB 和 AOF 的优点,Redis 4.0 引入了 RDB-AOF 混合持久化 机制。此机制以 AOF 持久化为基础,当开启混合持久化后,AOF 文件重写时会采用一种特殊的方式:
- RDB 格式开头:在 AOF 文件重写时,会将当前内存中的所有数据以 RDB 格式 写入新 AOF 文件的开头部分。
- AOF 格式追加:RDB 数据块写入完成后,后续的增量数据(即在重写过程中主进程接收到的写命令)会以 AOF 格式 追加到新文件的末尾。
因此,混合持久化后的 AOF 文件结构是:[RDB 数据块][AOF 命令流]。
优缺点
优点
- 快速启动:由于 AOF 文件的开头是 RDB 格式,Redis 启动时可以直接加载 RDB 部分,大大加快了恢复速度。
- 数据安全性高:RDB 部分加载完成后,再执行 AOF 命令流,保证了数据的最新状态,减少了数据丢失的风险(与纯 RDB 相比)。
- 文件体积相对较小:相比于纯 AOF 文件,混合持久化文件在重写后通常更小,因为 RDB 部分是压缩的。
缺点
- 兼容性问题:混合持久化后的 AOF 文件格式与旧版 Redis 不兼容,无法向下兼容。
- 重写开销:虽然相比纯 AOF 重写有所优化,但重写过程仍然涉及
fork()和磁盘 I/O,会消耗一定资源。