Redis持久化
核心思想:为什么需要持久化?
Redis是一个基于内存的数据库,其高速性能源于此,但也带来了致命弱点:一旦服务器宕机,所有内存数据将全部丢失。为了解决这个问题,Redis提供了持久化机制,将内存中的数据保存到磁盘,以便在服务重启时能够恢复数据,避免了从后端慢速数据库恢复数据的巨大压力和性能瓶颈。
Redis主要支持两种持久化方式:RDB(快照) 和 AOF(只追加文件)。
一、 RDB (Redis DataBase) 持久化 - 快照模式
RDB的核心思想是在某一时间点,将Redis内存中的数据完整地生成一个快照文件(dump.rdb)。
1. 触发方式
- 手动触发:
save: 阻塞主进程,直到快照完成。线上禁用。bgsave: 非阻塞。主进程fork一个子进程来执行快照,主进程继续处理客户端请求。这是推荐的方式。
- 自动触发:
redis.conf中配置save <seconds> <changes>规则,例如save 900 1表示900秒内有1次写入,则自动触发bgsave。- 主从复制时,从节点请求全量同步,主节点会触发
bgsave。 - 执行
shutdown命令(且未开启AOF时)。 - 执行
debug reload命令。
2. bgsave 工作流程与原理
- 主进程
fork一个子进程。fork过程是阻塞的,但通常很快。 fork利用写时复制(Copy-on-Write, COW)机制。子进程共享父进程的内存页表,不立即复制物理内存。- 子进程负责读取内存数据,并将其写入一个临时的RDB文件。
- 在子进程写快照期间,如果主进程接收到写命令并需要修改某块数据,操作系统会复制这块数据的物理内存页,让主进程修改副本,而子进程继续读取原始数据,保证了快照的一致性。
- 子进程完成快照后,用原子操作将临时文件替换掉旧的
dump.rdb文件。 - 子进程退出,通知主进程完成。
3. RDB 优缺点
- 优点:
- 恢复速度快:RDB文件是紧凑的二进制格式,加载它来恢复数据远快于AOF。
- 文件体积小:经过压缩(如LZF),文件体积远小于内存数据大小,适合备份和数据传输。
- 缺点:
- 数据丢失风险高:RDB是定时快照,如果两次快照之间发生宕机,会丢失这段时间的所有数据,无法做到秒级持久化。
fork开销大:fork子进程是重量级操作,会消耗CPU和内存资源,频繁执行成本高,可能导致主进程短暂阻塞。
二、 AOF (Append Only File) 持久化 - 日志模式
AOF的核心思想是将Redis执行的每一个写命令都以文本协议格式记录到一个日志文件中。
1. AOF 实现机制 - “写后日志”
Redis采用“写后日志”策略,即先执行命令修改内存数据,成功后再记录日志。 * 优点:避免了对命令的语法检查,且不会阻塞当前写操作。 * 潜在风险:如果在写完内存、但还未写入日志时宕机,会丢失该命令的数据。
AOF的完整过程分为三步:命令追加 (append) -> 文件写入 (write) -> 文件同步 (sync)。
2. 写回策略 (appendfsync)
控制何时将日志真正写入磁盘,体现了性能与可靠性的权衡(trade-off)。
always: 同步写回。每个命令执行完后,立刻fsync到磁盘。最安全,但性能最差。everysec(默认): 每秒写回。命令先写入内核缓冲区,每秒钟由一个后台线程执行一次fsync。性能和安全的最佳折中,最多丢失1秒数据。no: 操作系统控制。由操作系统决定何时将缓冲区数据刷到磁盘。性能最好,但最不安全。
3. AOF 重写 (Rewrite) - 文件瘦身
为了解决AOF文件无限增大的问题,Redis提供了AOF重写机制。
- 原理:不是读取旧的AOF文件进行优化,而是
fork一个子进程,直接读取当前内存中的数据,并为每个键生成一条最优的写入命令,最终生成一个全新的、更小的AOF文件。例如,对一个计数器的100次INCR操作,在重写后会变成一条SET命令。 - 触发时机:由
auto-aof-rewrite-percentage和auto-aof-rewrite-min-size两个配置项自动触发。 - 重写过程中的数据一致性:
- 主进程
fork出重写子进程。 - 在子进程重写期间,主进程接收到的新写命令会同时写入旧的AOF缓冲区和AOF重写缓冲区。
- 子进程完成重写后,通知主进程。
- 主进程将AOF重写缓冲区中的增量命令追加到新AOF文件的末尾。
- 用原子操作将新文件替换旧文件。
- 主进程
4. AOF 优缺点
- 优点:
- 数据可靠性高:根据写回策略,最多只丢失1秒的数据。
- 可读性好:AOF文件是文本格式,易于理解和修复。
- 缺点:
- 文件体积大:相比RDB,AOF文件通常更大。
- 恢复速度慢:恢复时需要逐条执行命令,速度远慢于RDB。
- 存在
fork开销:AOF重写同样需要fork子进程。
三、 RDB 和 AOF 混合模式 (Redis 4.0+)
为了结合两者的优点,Redis 4.0引入了混合持久化。
- 工作方式:当触发AOF重写时,
fork的子进程不再是生成命令,而是将当前内存数据以RDB格式写入新AOF文件的开头,然后主进程将重写期间的增量写命令以AOF格式追加到文件末尾。 - 优势:
- 快速恢复:加载时,先像RDB一样快速加载文件头部的快照部分。
- 高可靠性:再加载文件末尾的AOF增量日志,保证了数据的完整性。
- 这个方案是目前生产环境中的主流选择。
四、 数据恢复与实践
恢复流程
- Redis重启时,会优先加载AOF文件(如果开启了AOF),因为它通常包含更完整的数据。
- 如果AOF加载失败或不存在,才会去加载RDB文件。
线上实践建议
- 性能优先,数据可重建:可以关闭持久化。
- 数据安全:开启混合持久化模式是最佳实践。
- 降低
fork影响:- 控制Redis实例的最大内存,避免
fork耗时过长。 - 避免多个实例在同一时间点进行持久化或重写操作。
- 在主从架构中,可以利用从节点来执行RDB备份,不影响主节点的性能。
- 控制Redis实例的最大内存,避免
- 合理配置:根据业务场景调整
save策略和AOF重写触发条件。
总结表
| 特性 | RDB (快照) | AOF (日志) | 混合模式 (推荐) |
|---|---|---|---|
| 数据可靠性 | 较低,丢失上次快照至今的数据 | 高,最多丢失1秒数据 (everysec策略) |
高,同AOF |
| 文件大小 | 小,二进制压缩 | 大,文本日志,需重写瘦身 | 较小,RDB头部+AOF尾部 |
| 恢复速度 | 快,直接加载内存镜像 | 慢,需重放所有命令 | 快,先加载RDB部分,再重放少量AOF增量 |
| 核心机制 | fork + 写时复制 (COW) |
命令追加 + 写回策略 + fork重写 |
AOF重写时,生成RDB格式文件头+AOF格式增量 |
| 适用场景 | 数据备份、灾难恢复、主从复制全量同步 | 对数据完整性要求高的场景 | 绝大多数生产环境 |