目录
[always 策略](#always 策略)
[everysec 策略(默认)](#everysec 策略(默认))
[no 策略](#no 策略)
Redis持久化有两种策略:RDB和AOF。RDB是定期备份,AOF是每次修改都备份。RDB不保证安全,AOF可以保证相对安全
RDB
RDB有两种定期备份的途经,一种是执行redis命令手动触发,另一种是通过修改配置文件让redis自动定期备份。
手动触发
非阻塞式
相关命令:
sql
//非阻塞式备份,期间可以执行其他命令
bgsave
执行流程:
redis使用新启动一个进程(而不是线程)的方式来进行后台备份。redis数据存放于内存,如果使用线程,备份线程和主线程访问同一块内存,此时需要加锁 、阻塞主线程。而使用进程的话,由于写时拷贝机制,调用bgsave时内存的状况会被完整保存,不会被中途修改,不需要进行加锁。所以使用进程是更加合适的
- 执行 bgsave 命令时,Redis 父进程首先判断当前是否存在其他正在执行的子进程(如 RDB/AOF 子进程),若存在,则 bgsave 命令直接报告执行失败。(这是因为,多个bgsave同时执行没有意义,数据差异并不大,而且还消耗很多CPU、内存资源)
- 父进程执行 fork 创建子进程,fork 过程中父进程会阻塞(但是备份的过程不会阻塞主进程)。
- 父进程 fork 完成后,bgsave 命令返回 "Background saving started" 信息,不再阻塞父进程,父进程可继续响应其他命令,子进程开始备份。
- 子进程创建 RDB 文件(存放于redis工作目录下,可通过配置文件修改),根据父进程内存生成临时快照文件,完成后对原有RDB文件进行原子替换。(为什么要这样?因为如果直接往原有RDB文件写入的话,一但这次bgsave被打断,原有的RDB文件就会被破坏,使得所有数据都无效)
RDB文件:
- RDB文件里存放的是压缩过后的redis数据(压缩可以节省空间,但是复原需要消耗CPU),存储的直接是二进制。
- redis-check-rdb命令可以检查一个rdb文件是否正确(如果rdb文件是错误的,可能会导致数据错乱甚至服务器无法启动)。
阻塞式
sql
//阻塞式备份,期间无法执行其他命令
save
自动触发
redis可以设置每隔多久或者每修改几次进行一次自动备份
通过配置文件修改自动触发的时机:

**当然,除了自己设置的触发时机,在服务器被正常关停等情况也会触发自动备份。**如果修改数据后没触发自动备份也没手动备份,并且redis服务崩掉了,那修改就会丢失。
AOF
一但AOF开启,redis服务器优先使用AOF文件进行数据恢复而不是RDB文件。
开启AOF
在redis.conf这个配置文件修改配置即可:

AOF文件
AOF文件以文本方式存放redis的操作记录,并不直接存二进制键值对。因此,使用AOF文件恢复数据要比RDB文件要慢很多。
每次写磁盘,就是在AOF文件末尾添加操作记录,不会修改文件中间的记录。正是因此,AOF模式下备份不需要经过"写到临时文件->然后再把原文件删除->给临时文件改名"这样的过程,就算redis服务突然崩了,也仅仅只是让某一条操作记录损坏,而不会影响前面所有的记录。
AOF有可读性好、容易修复(因为是命令文本)等优点。
AOF
AOF理论上是每一次修改都会写磁盘,但实际上:
- 在AOF模式下,修改会首先被存入内存中的aof_buff缓冲区,一次时间循环后才会写磁盘。
- AOF提供了三种策略,分别对应三种安全级别,安全性越高效率越低,具体如何选择取决于业务
AOF三种策略
always 策略
-
aof_buf刷新时机
每个写命令执行完毕后立即调用flushAppendOnlyFile函数,该函数会执行write,将当前aof_buf中的所有命令写入内核缓冲区,然后清空aof_buf。
⏱️ 频率:每个写命令后一次。 -
内核缓冲区刷新时机
同一个调用过程中,write之后立刻执行fsync,强制将本次写入内核缓冲区的数据同步到磁盘。
⏱️ 频率:每个写命令后立即fsync。
结论:在
always下,aof_buf一有数据就被write并清空,且内核缓冲区立刻被fsync,两者几乎同步发生,数据最安全,但性能最低。
everysec 策略(默认)
-
aof_buf刷新时机
Redis 主线程在每次事件循环的beforeSleep阶段(处理完一批客户端命令后,准备进入多路复用的等待前),都会调用flushAppendOnlyFile。该函数将aof_buf中的所有数据通过write写入内核缓冲区,并清空aof_buf。
只要事件循环在运行,这个动作就会非常频繁------可能每处理几个命令就发生一次,远高于每秒一次。
⏱️ 频率:每个事件循环批次一次(通常每毫秒级都可能发生)。 -
内核缓冲区刷新时机
flushAppendOnlyFile中不会直接执行fsync。而是由 Redis 专门启动的一个后台线程,每隔 1 秒钟调用一次fsync,将这一秒内内核缓冲区中积累的 AOF 数据强制刷盘。
如果主线程执行write时,发现上一次后台fsync尚未完成,为了不阻塞主线程,它甚至会跳过本次write(即不写入内核缓冲区,aof_buf不清空,等下次再写),以保证主线程的响应速度。
⏱️ 频率:后台线程每秒执行一次fsync。
结论:
everysec下,aof_buf不断被快速清空并写入内核缓冲区(减少内存积压),但内核缓冲区的数据会积攒最多 1 秒,再由fsync批量刷盘。这是一种极好的平衡:性能较高,最多丢失 1-2 秒的数据。
no 策略
-
aof_buf刷新时机
与everysec完全相同:同样在事件循环的beforeSleep中调用flushAppendOnlyFile,将aof_buf的内容write到内核缓冲区并清空aof_buf。
⏱️ 频率:每个事件循环批次一次。 -
内核缓冲区刷新时机
Redis 完全不调用fsync。内核缓冲区的数据何时写入磁盘,完全由操作系统自行决定。
在 Linux 系统中,通常会由内核线程pdflush定期(比如每 30 秒)或在脏页比例达到阈值时,将页缓存刷新到磁盘。
⏱️ 频率:操作系统决定(典型约 30 秒一次)。
结论:
no策略下,aof_buf依然被频繁地write并清空,但内核缓冲区很可能长时间不刷盘,一旦宕机可能丢失最近数十秒的数据,性能最高,安全性最低。
修改redis.conf这个配置文件即可:

AOF文件的重写
这个主要是可以缩小AOF文件的体积,加快reids服务的启动时间,以及节省磁盘空间。缩小的方式就是等价(set key 111和del key 就等价于什么都不做)。 AOF文件的重写可以手动重写和自动重写。 实际上,AOF重写是直接把内存中的状态保存下来,并不会遍历原有的AOF文件进行等价缩小,这样太慢了。
重写流程
-
如果当前进程正在执行 AOF 重写,则新请求不执行(因为很短时间内多次重写没有意义)。如果当前进程正在执行 bgsave 操作,则重写命令延迟到 bgsave 完成之后再执行。(首先重写并不是特别重要知识一种优化,其次两个一同执行可能会导致资源消耗峰值更高,造成redis服务崩溃)
-
父进程执行 fork 创建子进程用于重写。
-
重写过程:
-
父进程 fork 之后,继续响应其他命令。所有修改操作同时写入两个缓冲区:常规 AOF 缓冲区(aof_buff)和 AOF 重写缓冲区(aof_rewrite_buff)。
-
**子进程仅拥有 fork 时刻的内存快照,**根据内存快照,将数据转换为命令并合并写入临时 AOF 文件。
-
临时文件写入完成后,子进程发送信号通知父进程。
-
父进程将 AOF 重写缓冲区中临时保存的命令追加到临时文件末尾。
-
用临时文件原子替换旧 AOF 文件。
-
为什么父进程还要把修改写入aof_rewrite_buff缓冲区?
子进程进行aof重写的同时,父进程可以执行其他命令,但是子进程看不到这些修改,也就不会把这些修改对应的操作记录保存到临时文件中。那么如果原有AOF文件被临时文件替换,就会造成一部分的修改丢失,并且假设此时aof_buff因为数据都被写到旧AOF文件而清空,在后续的AOF写入中也不会把这部分修改存进去。但是重写被触发后会把这部分数据给填补上(因为重写是直接将内存数据转换成命令存放,并不依赖旧的AOF文件),但是一但断电或者服务崩掉,内存中的数据也丢失了,直接造成这部分数据永远丢失。任何AOF策略都不能保证不丢失,这不符合AOF的初衷。
把子进程重写期间父进程所做的修改存到aof_rewrite_buff缓冲区中,等到子进程重写成功后,父进程把****aof_rewrite_buff缓冲区的内容追加到临时文件末尾。在此期间,不会有命令被执行(redis单线程)。这就支持了AOF模式下的安全性。
为什么重写要涉及临时文件而普通备份则不?
很简单,重写会大范围修改AOF文件,影响太大。
手动重写
bash
bgrewriteaof
自动重写

配置项 1:auto-aof-rewrite-percentage
-
作用:触发重写的增长率阈值
-
默认值:100
-
说明:当前AOF文件体积比上次重写后增长了多少百分比时触发。设置为 0 可禁用自动重写。
配置项 2:auto-aof-rewrite-min-size
-
作用:触发重写的文件大小下限
-
默认值:64mb
-
说明:避免在AOF文件还很小的时候就频繁重写。
混合持久化
就是在触发AOF重写后,会把当前内存中的数据按照RDB文件的那种二进制压缩格式来存放,以此来加快服务重启速度以及进一步缩小体积。而不是存放操作记录。
但是AOF下的普通备份仍旧是按照文本方式在AOF文件中追加操作记录(AOF备份比较频繁,如果AOF每次备份都直接存放二进制数据,那么必须使用临时文件保证大部分数据不会失效,但是这样效率会大大降低)。
在混合持久化情况下,AOF文件中可能会出现两种格式的内容:
