在上一篇中,我们探讨了 Redis 的分布式锁。今天,我们回归 Redis 的本质——内存数据库。
既然是“内存”数据库,大家最担心的就是一个问题:断电了怎么办? 如果服务器宕机,内存里的数据就会瞬间蒸发,这对业务来说是灾难性的。
为了解决这个问题,Redis 提供了强大的持久化机制,将内存数据写入磁盘。本文将深入扒开 RDB、AOF 以及 Redis 4.0 引入的混合持久化的底层细节。
一、 RDB:给内存拍张“照片”
RDB (Redis Database Backup file),又被称为数据快照。
它的原理非常直观:在指定的时间间隔内,将内存中的所有数据集快照写入磁盘。 恢复时,直接将快照文件读入内存。
1. 触发机制
在 redis.conf 中,我们可以配置触发规则:
Bash
save 900 1 # 900秒内,至少1个key被修改,则触发
save 300 10 # 300秒内,至少10个key被修改,则触发
save 60 10000 # 60秒内,至少10000个key被修改,则触发
除了自动触发,我们还可以手动执行命令:
-
save:由主进程执行。注意! 因为 Redis 是单线程的,主进程去写磁盘,会直接阻塞所有客户端请求,生产环境绝对禁止使用。
-
bgsave:Background Save。Redis 会在后台异步进行快照操作,不阻塞主进程。
2. 原理深度剖析:bgsave 与 它的底层实现:Copy-On-Write (写时复制)
写时复制的意思其实就是主线程在进行写操作的时候,先复制备份一份,在备份的这个文件上去进行写操作,这样子进程读操作就可以保证一直读的是之前的那个旧版本。
问题场景:Redis 一边在“拍照”(持久化),一边还在“干活”(处理用户写请求)。如果数据一直在变,照片怎么拍?比如拍照要 1 分钟,这 1 分钟内数据变了怎么办?
为了解决这个问题,Redis 引入了 Fork 和 COW (Copy-On-Write) 机制。
第一步:Fork 子进程
当执行 bgsave 时,主进程会调用操作系统的 fork() 系统调用,创建一个子进程。
-
关键点:
fork不会复制原本的 10GB 内存数据(否则内存瞬间爆炸且耗时极长)。 -
它只复制主进程的页表(Page Table)。页表可以理解为内存数据的“目录”。
-
结果:子进程诞生的一瞬间,它手里的“目录”和主进程一模一样,指向同一块物理内存。这个过程极快,只阻塞主进程几毫秒。
第二步:写时复制 (Copy-On-Write)

fork 结束后,主进程继续响应客户端请求,子进程负责写文件。
此时,主子进程共享同一份物理内存。
-
如果主进程是读数据:大家相安无事。
-
如果主进程要写数据(比如修改 Key A):
-
操作系统发现这块内存被共享且标记为“只读”,触发中断。
-
操作系统将 Key A 所在的**那一页内存(4KB)**复制一份副本。
-
主进程在副本上修改 Key A。
-
子进程继续读取原件。
-
结论:
通过 COW 机制,子进程拿到的永远是 fork 那一瞬间的“时间冻结”数据。无论主进程怎么改,生成的 RDB 文件都是绝对纯净、一致的快照。
3. RDB 优缺点
-
优点:恢复速度极快(解压二进制文件即可);文件体积小。
-
缺点:数据安全性低。RDB 是间隔执行的,如果每 5 分钟拍一次,Redis 在第 4 分钟宕机,你就会丢失这 4 分钟的所有数据。
二、 AOF:记账员的“流水账”
简单来说RDB是拍照AOF就是记录所有的命令。
AOF (Append Only File),意思是追加文件。
它的逻辑与 RDB 完全不同:Redis 每执行一条写命令,就把它以文本协议的格式追加到日志文件的末尾。
恢复时,Redis 就像重播电影一样,把日志里的命令从头到尾执行一遍。
1. 刷盘策略 (fsync)
AOF 解决了 RDB 丢数据的问题,但“写文件”也是有磁盘 IO 开销的。Redis 提供了三种策略:
-
Always:同步刷盘。每执行一条写命令,立马强制写入磁盘。
-
优点:数据绝对安全。
-
缺点:性能极差,吞吐量低。
-
-
Everysec (默认):每秒刷盘。先把命令写到缓冲区,每隔 1 秒将缓冲区写入磁盘。
-
优点:性能与安全的平衡点,最多丢失 1 秒数据。
-
-
No:操作系统看着办。性能最好,但不可控。
2. AOF 重写 (Rewrite)
随着时间推移,AOF 文件会越来越大。
比如你对 count 执行了 100 次 INCR,最终 count=100。AOF 文件里存了 100 条命令,但恢复数据时,其实只需要一条 SET count 100 就够了。
为了给日志“瘦身”,Redis 提供了 bgrewriteaof 命令:
-
Redis 会创建一个子进程。
-
子进程读取当前的内存状态。
-
用最少的命令构建一个新的 AOF 文件,替换掉旧的大文件。
3. AOF 优缺点
-
优点:数据安全。使用
everysec策略,顶多丢失 1 秒数据。 -
缺点:恢复速度慢(要重新执行所有命令);文件体积通常比 RDB 大。
三、 混合持久化(升级版”的 AOF 重写(瘦身)方式)
简单来说就是先把当前现有的存为RDB格式,然后新增的用AOF格式追加在后面。
在 Redis 4.0 之前,我们经常陷入纠结:用 RDB 怕丢数据,用 AOF 怕恢复太慢。
Redis 4.0 推出了 RDB-AOF 混合持久化,作为默认配置,完美解决了这个问题。
1. 核心原理
混合持久化发生在 AOF 重写 的过程中。
当 Redis 重写 AOF 文件时,它不再只是单纯地把内存转成 AOF 命令,而是:
-
前半部分:将当前的内存数据,以 RDB (二进制快照) 的格式写入 AOF 文件开头。
-
后半部分:在重写期间产生的新增量数据,依然以 AOF (文本命令) 的格式追加在后面。
2. 最终的文件结构
打开一个开启了混合持久化的 .aof 文件,你会发现:
-
开头是乱码一样的二进制数据(RDB 快照)。
-
末尾是可读的文本命令(AOF 增量日志)。
3. 压倒性的优势
-
启动超快:Redis 启动时,先加载开头的 RDB 部分,速度飞快。
-
数据不丢:加载完 RDB 后,再执行末尾少量的 AOF 命令,补全最后时刻的数据。

四、 总结与选型建议
| 特性 | RDB (快照) | AOF (日志) | 混合持久化 |
| 底层原理 | Fork + Copy-On-Write | 追加写 + 重写 | RDB + AOF |
| 恢复速度 | 快 | 慢 | 快 |
| 数据安全性 | 低 (可能丢几分钟) | 高 (丢1秒) | 高 |
| 文件大小 | 小 | 大 | 中等 |
给开发者的建议:
-
生产环境:强烈建议开启 混合持久化(Redis 4.0+ 默认开启)。这是目前的最佳实践。
-
纯缓存模式:如果你完全不在乎数据丢失(比如只是做数据库的缓存,丢了可以回源查 MySQL),可以关闭所有持久化,获得极致的性能。
-
永远不要只开启 RDB:除非你这台 Redis 是用来做纯粹的离线备份,否则数据丢失的风险在生产环境中是不可接受的。

2746

被折叠的 条评论
为什么被折叠?



