目录
[RDB 异步持久化的底层原理](#RDB 异步持久化的底层原理)
在 Redis 的默认配置文件(redis.conf)中,RDB 是 默认开启 的,而 AOF(Append-Only File)需要手动配置开启。
RDB
定义
RDB : Redis Database Backup File (Redis数据备份文件),也被叫做Redis数据快照。
把内存中的所有数据都记录到磁盘文件中,当Redis实例故障重启后,读取磁盘快照文件,恢复数据。
Redis有触发 RDB 的机制,可以在redis.conf 配置文件中找到
- save 900 1 # 900秒内,如果至少有1个key被修改,则执行 bgsave 命令
 - save 300 10 # 300秒内,如果至少有10个key被修改,则执行 bgsave 命令
 - save 60 10000 # 60秒内,如果至少有10000个key被修改,则执行 bgsave 命令
 
除此之外,可以手动执行命令,触发 RDB
- save 命令: 由Redis主进程来执行RDB,会阻塞所有命令
 - bgsave命令: 开启子进程执行RDB,避免主进程受到影响
 
RDB 异步持久化的底层原理
RDB 异步持久化 即bgSave 就是开启一个 子进程 ,由子进程读取 内存 数据,并写入RDB文件。
bgSave 对主进程几乎是0阻塞的,但是有一个过程是阻塞主进程的,那就是 bgSave 刚开始时,fork 主进程得到子进程 (主要是把页表复制给子进程),子进程共享主进程的内存数据,这个 fork 的过程是阻塞的,Redis在 fork 中只能做这一件事。不能去接收用户请求。
子进程在执行 bgSave 时读取共享内存的数据,主进程如果在写内存数据,可能会造成冲突。因此为了避免这个问题。底层会使用一种 copy-on-write的技术:
- 内存数据会被标记为Read-Only是只读的
 - 当主进程执行写操作时,则会拷贝一份数据,在拷贝的数据上执行写操作
 
图示:

1.执行bgsave命令,Redis父进程判断当前进程是否存在其他正在执行的子进程,如RDB/AOF子进程,如果存在bgsave命令直接返回。
2.父进程执行fork创建子进程,fork过程中父进程会阻塞。
3.父进程fork完成后,bgsave命令返回"Background saving started"信息并不再阻塞父进程,可以继续响应其他命令。
4.子进程创建RDB文件,根据父进程内存生成临时快照文件,完成后对原有文件进行原子替换。
5.进程发送信号给父进程表示完成,父进程更新统计信息
什么是fork进程
fork 是Linux/Unix系统的一个核心系统调用,它的作用是创建一个与父进程几乎完全相同的子进程。
在Redis的BGSAVE场景中:
- 父进程:就是主要的Redis服务器进程,负责接收和处理客户端的命令
 - 子进程:通过fork创建的进程,是父进程在fork那个时间点的"副本"
 关键理解:为什么用 fork?
- 不影响服务:子进程做耗时的磁盘I/O操作,父进程继续服务客户端
 - 数据一致性:子进程拥有fork时刻的内存数据快照,保证RDB文件数据一致
 - 写时复制:父子进程共享相同内存页,只有当某页被修改时,系统才会真正复制该页,非常高效
 
优缺点
**优点:**宕机后恢复速度快、文件体积小
缺点:
- 数据安全性有问题,因为RDB执行间隔时间长,两次RDB之间写入的数据有丢失风险。但是RDB的间隔时间又不能设置的过短,因为RDB的过程是比较耗时的,如果间隔时间过短,根本忙不过来。
 - fork子进程(复制页表)、写出RDB文件都比较耗时。
 
写出:子进程将Redis内存中的数据序列化并写入到磁盘文件的过程
总结:
|--------------------------------------------------------------------------------------------|
| 1.RDB是一个紧凑压缩的二进制文件,代表Redis在某个时间点上的数据快照,非常适用于备份,全量复制等场景                                     |
| 2.Redis加载RDB恢复数据远远快于AOF的方式                                                                 |
| 3.RDB ⽅式数据没办法做到实时持久化 / 秒级持久化。因为 bgsave 每次运⾏都要执⾏ fork 创建子进程,属于重量级操作,频繁执⾏成本过⾼                |
| 4.RDB ⽂件使⽤特定⼆进制格式保存,Redis 版本演进过程中有多个 RDB 版本,兼容性可能有⻛险(即老版本的redis的rdb文件放到新版本的redis中,不一定能被识别) |
| 5.RDB最大的问题就是不能实时的持久化保存数据。在两次生成快照之间,实时的数据可能会随着重启而丢失                                         |
AOF
定义
AOF全称为Append Only File (追加文件) 。Redis处理的每一个写命令 都会记录在AOF文件。所以可以把AOF文件看做命令日志文件。
AOF 执行的频率,写 日志文件 **的频率。**默认是每秒钟做一次AOF。
- always:同步刷盘,写日志文件的操作是由主进程在写入内存数据后完成,性能影响大
 - everysec:每秒刷盘,写内存后先把命令放入AOF缓冲区,然后每隔一秒将缓冲区数据写入AOF文件
 - no:操作系统控制,写内存后把命令放AOF缓冲区,由操作系统决定何时将缓冲区内容写入AOF文件
 
AOF文件重写
因为是记录命令,AOF文件会比RBD文件大得多,而且AOF会记录对同一个key的多次写操作,但只有最后一次写操作才有意义。通过执行bgrewriteaof命令,可以让AOF文件执行重写功能,用最少的命令达到相同的效果,但这个过程会占用大量的资源。
可以配置触发 bgrewriteaof 的阈值。
- 文件增长百分比:AOF文件比上次文件 增长超过多少百分比则触发重写AOF文件
 - 文件体积最小多大以上才触发重写AOF文件
 
优缺点
**优点:**数据安全性更高,例如everysec策略,只会丢失1秒以内的数据
缺点:
- 宕机后恢复速度慢,因为AOF文件记录的是命令,需要依次执行
 - 文件体积大,需要进行AOF文件重写,此时会占用大量资源
 
混合持久化
AOF 和 RDB 各自有优缺点,为了同时拥有上述两种持久化的优点
Redis 4.0 推出了 RDB-AOF 混合持久化,以AOF持久化为基础
开启混合持久化后,当 AOF 文件重写时
- 将当前内存数据以 RDB 格式写入新 AOF 文件的开头
 - 后续增量数据以 AOF 格式追加到文件末尾
 
文件结构:[ RDB 数据块][ AOF 命令流]
混合持久化结合了 RDB 和 AOF 持久化的优点,开头为 RDB 的格式,使得 Redis 可以更快的启动,
同时结合 AOF 的优点,又减低了大量数据丢失的风险,提高了数据安全性。
但AOF文件格式变化导致混合持久化是不能向下兼容的
不能向下兼容:一旦开启了混合持久化,生成的AOF文件就变成了一个"新物种",这个新格式的文件无法被旧版本的Redis识别和加载