redis虽然是一个内存数据库,但数据存在内存中是不持久的,想要持久化存储还得把数据存在硬盘上,redis也会把数据存在硬盘上,只不过这硬盘数据是用来恢复redis在内存的存储的,实际上读写还是在内存。
Redis 支持 RDB 和 AOF 两种持久化机制,持久化功能有效地避免因进程退出造成数据丢失问题,当下次重启时利用之前持久化的文件即可实现数据恢复。
前置知识:redis属于客户端服务器类型,同时内部是单线程模型
一、RDB---定期备份
RDB可以定期地把redis中的数据备份到硬盘中,用来恢复内存数据,就相当于"快照"
1.1触发机制
RDB有手动,自动两种触发机制。
手动触发对应 save和bgsave命令
- save命令 :执行save会使redis全力以赴去进行数据复制,这时候会阻塞redis客户端其他操作,坏处类似(key *)基本不会使用这个命令
- bgsave命令:Redis 进程执行 fork 操作创建子进程,RDB 持久化过程由子进程负责,完成后自动
结束。阻塞只发生在 fork 阶段,⼀般时间很短。
redis内部进行RDB操作,基本都使用类似bgsave方式
bgsave流程:

1.执行 bgsave 命令,Redis 父进程判断当前是否存在其他正在执行的子进程(如 RDB/AOF 子进程),如果存在,bgsave 命令直接返回。
2.父进程执行 fork 创建子进程,fork 过程中父进程会阻塞。通过 info stats 命令查看 latest_fork_usec 选项,可以获取最近一次 fork 操作的耗时,单位为微秒。
3.父进程 fork 完成后,bgsave 命令返回 "Background saving started" 信息,不再阻塞父进程,父进程可以继续响应其他命令。
4.子进程创建 RDB 文件,根据父进程内存生成临时快照文件,完成后对原有文件进行原子替换。执行 lastsave 命令可以获取最后一次生成 RDB 的时间,对应 info 统计中的 rdb_last_save_time 选项。
5.子进程发送信号给父进程表示完成,父进程更新统计信息。
自动触发 :
1.通过save配置,比如save m n表示"数据在m秒内发生n次修改"就自动触发。
2.从节点进行全量复制时,主节点自动触发,然后将RDB文件交给从节点
3.shutdown命令关闭redis时触发
redis配置文件中的一些默认配置

1.2 RDB文件
RDB操作会产生RDB文件
RDB的文件内容是默认通过"LZF"算法进行压缩 处理的二进制数据文件
虽然压缩会消耗CPU但可以大大降低文件体积,所以还是尽量开着
RDB文件内容千万不要擅自修改,redis重启会尝试加载RDB文件,如果文件被改坏了可能会导致redis服务器无法启动
RDB文件只有一份,进行"快照操作"时会先创建一个临时RDB文件,等复制好了就会替换,新文件的Inode会更新,可以根据这个判断文件新旧。
1.3 RDB优缺点
-
RDB 是一个紧凑压缩的二进制文件,代表 Redis 在某个时间点上的数据快照。非常适用于备份、全量复制等场景。例如每 6 小时执行 bgsave 备份,并把 RDB 文件复制到远程机器或文件系统(如 HDFS)中用于灾备。
-
Redis 加载 RDB 恢复数据的速度远快于 AOF 方式。
-
RDB 方式无法做到实时持久化或秒级持久化。因为 bgsave 每次运行都要执行 fork 创建子进程,属于重量级操作,频繁执行成本过高。
-
RDB 文件使用特定二进制格式保存,Redis 版本演进过程中存在多个 RDB 版本,兼容性可能存在风险。
二、AOF---实时备份
上述说到RDB是一个定期备份操作,如果在完成一次备份后,瞬间涌入大量操作,redis还没来得及自动备份就炸了,那数据不是都丢了吗?
这里AOF就能解决这个问题
先做一个了解,AOF文件是文本文件,AOF是默认关闭的,开启AOF后redis就通过AOF来恢复数据不再用RDB了。
2.1 AOF工作流程
redis要求的就是"快",使用AOF又读内存又写硬盘的,这能快吗?
其实没影响,AOF是把数据都写到一个内存缓冲区 ,写的差不多的时候在一并写入硬盘(有效减少磁盘IO),而且AOF写入硬盘是"顺序写入 ",硬盘在"顺序读写"的时候会更快一些

1.所有的写入命令会追加到 aof_buf(缓冲区)中。
2.AOF 缓冲区根据对应的策略向硬盘做同步操作。
3.随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩的目的。
4.当 Redis 服务器启动时,可以加载 AOF 文件进行数据恢复。
2.2 缓存区文件同步
AOF还有一个问题,如果我在写入缓冲区的时候,redis炸了可咋办,数据丢了吗?
对于redis来说确实丢了,不过我们可以牺牲性能来提高缓存刷新频率进而提高可靠性
AOF 缓冲区同步文件策略:从上到下频率越来越低,一般用第二个
| 可配置值 | 说明 |
|---|---|
| always | 命令写入 aof_buf 后调用 fsync 同步,完成后返回 |
| everysec | 命令写入 aof_buf 后只执行 write 操作,不进行 fsync。每秒由同步线程进行 fsync |
| no | 命令写入 aof_buf 后只执行 write 操作,由 OS 控制 fsync 频率 |
2.3 重写机制
AOF 重写是 Redis 解决 AOF 文件体积膨胀、优化数据恢复效率的核心手段。
2.3.1 为什么 AOF 重写能缩小文件?
AOF 重写并不需要读取、分析或合并旧的 AOF 文件,而是直接读取 Redis 内存中的当前键值对状态来生成新文件。其缩小体积的逻辑如下:
- 丢弃过期数据:已经过期的数据在内存中可能已被删除或不再有效,重写时不会将其写入新文件。
- 剔除无效命令 :旧日志中大量的中间状态(如
SET a 1,SET a 2,SET a 3)在重写时只会被简化为最终状态(SET a 3)。 - 删除已删除的数据 :例如先
SET key val后又DEL key,这两条指令在重写后的文件中都会消失。 - 合并多条指令 :对于集合类操作,多条插入指令(如 100 次
Lpush)会被合并为一条指令(Lpush list v1 v2 ... v100),极大地节省了报头空间。
2.3.2 AOF 重写的触发条件
重写可以通过手动干预或配置参数自动触发:
① 手动触发
- 客户端直接执行命令:
BGREWRITEAOF。
② 自动触发
基于 redis.conf 中的两个关键配置参数:
auto-aof-rewrite-percentage 100:- 表示当前 AOF 文件大小超过上一次重写后文件大小的百分之多少时触发。
100意味着文件体积翻倍时触发。
- 表示当前 AOF 文件大小超过上一次重写后文件大小的百分之多少时触发。
auto-aof-rewrite-min-size 64mb:- 表示触发重写的最小文件体积。防止在文件还很小时(例如只有几 KB)就频繁进行重写操作。
2.3.3 AOF 重写的详细流程
AOF 重写采用 "后台子进程" 方式执行,确保主进程可以继续处理客户端请求。
详细步骤:
- 创建子进程 (Fork) :
- 主进程调用
fork()创建子进程。子进程与主进程共享此时的内存快照。
- 主进程调用
- 子进程后台重写 :
- 子进程遍历内存数据,将每个键值对转换成 Redis 命令写入到新的临时 AOF 文件中。
- 主进程同步处理增量 (Rewrite Buffer) :
- 在子进程重写期间,主进程仍在处理新的写请求。
- 这些新产生的写命令会被同时写入
AOF 缓冲区(保证旧 AOF 完整性)和AOF 重写缓冲区(图3.2)(保证新 AOF 不丢失重写期间的数据)。
- 子进程完成通报 :
- 子进程写完内存快照后,向主进程发送一个信号。
- 增量数据补录 (关键阻塞点) :
- 主进程收到信号后,会将
AOF 重写缓冲区中的所有增量命令写入到新的临时 AOF 文件中。 - 注意:此步骤由主进程执行,会产生短暂阻塞。
- 主进程收到信号后,会将
- 原子替换 :
- 主进程使用新的 AOF 文件原子地覆盖旧文件,至此重写完成。

图3.1存在意义:你在写新的AOF文件时redis炸了,就靠对老文件的修改来完成"实时备份"
提示 :从 Redis 7.0 开始,引入了 Multi-Part AOF,取消了复杂的"重写缓冲区",改用增量 AOF 文件(Incr AOF)来存储重写期间的数据,进一步降低了主进程的阻塞风险和内存消耗。
三、混合持久化
AOF是文本数据,读写成本很高,这时就引入了混合持久化,把AOF和RDB优点一同纳入
就一个修改点:在AOF触发重写时,将重写数据改为RDB那种二进制格式
AOF与RDB优先级:AOF更优
