目录
[1.1 RDB的触发方式](#1.1 RDB的触发方式)
[1.2 bgsave的流程](#1.2 bgsave的流程)
[1.3 实际执行](#1.3 实际执行)
[1.4 RDB的优缺点](#1.4 RDB的优缺点)
[2.1 开启AOF](#2.1 开启AOF)
[2.2 AOF文件写入](#2.2 AOF文件写入)
[2.3 AOF重写机制](#2.3 AOF重写机制)
[2.4 AOF重写的流程](#2.4 AOF重写的流程)
[2.5 混合持久化](#2.5 混合持久化)
[2.6 数据恢复](#2.6 数据恢复)
Redis的直观的特性就是相比数据库更快,效率更高,这是因为Redis的数据存储在内存上,所以我们可以做到快速读写,但是如果数据值存放到内存上是不持久的,如果主机或进程重启,数据就不存在了。
所以我们Redis的数据既要存储在内存上以此来实现"快",同时也要存储到硬盘上,以此来实现持久化。这样如果Redis重启后也可以从硬盘中读取数据来恢复内存中的数据
那么Redis该如何把数据存储到硬盘上呢,Redis向我们提供了两种策略
RDB:Redis DataBase :定期备份
AOF:Append Only File:实时备份
一、RDB
RDB定期把我们Redis内存中的数据,都写入到硬盘中,生成一个"快照"。可以理解为Redis给内存当前存储的数据赶紧拍个照片生成一个文件,存储到硬盘中,后续如果Redis重启,就可以通过硬盘里的"快照"文件恢复内存的数据
1.1 RDB的触发方式
1. 手动触发
我们可以通过在Redis命令行中输入指定命令来触发快照的生成
- save :执行save的时候,Redis就会把让所有资源都用来进行"快照生成"操作,此时就会阻塞Redis的其他命令,所以我们一般不建议使用save命令
- bgsave :bg就是background的意思,所以这个"快照生成"的过程是在背后进行的,不会阻塞Redis,也就不会影响Redis处理别的命令
2. 自动触发
除了在Redis客户端命令行输入指令的方式,我们还可以在Redis的配置文件中进行配置,让Redis在一定时间内自动进行RDB
在etc/redis文件夹中有一个redis.conf配置文件

文件中这里的配置就是对RDB的自动触发配置
3600 1:在3600秒(1小时)至少有1次数据修改
300 100:在300秒(5分钟)至少有100次数据修改
60 10000:在60秒(1分钟)至少有10000次数据修改

如果觉得这个配置不符合我们的业务需求,也可以在这个配置文件中进行修改
同时我们可以在这个配置文件中查看快照文件的位置


我们进入快照文件查看,这个rdb文件是一个二进制文件,内存中的数据以二进制的形式保存到这个文件中,redis重启的时候就会去读取这个文件,从而恢复内存中的数据,如果我们对这个文件进行了修改,redis服务可能就无法启动了

1.2 bgsave的流程

- 当我们触发bgsave命令时,父进程首先会判断当前是否有其他正在执行的子进程,如果存在bgsave直接返回,不做任何操作
- 如果没有其他子进程,父进程调用fork(),就会创建一个子进程,这个子进程会拥有父进程的所有信息,可以说父进程和子进程是相同的,子进程的物理内存是通过写时复制机制和父进程共享
- 写时复制:如果是读操作的命令,子进程仍然和父进程共享内存空间,但是如果客户端输入写操作的命令,父进程就会申请一块新的空间,在这个新的空间进行修改。
- 比如:父进程有个变量n=10,调用fork(),子进程也会有一个变量n=10,并且和父进程的n变量共享一块内存空间,父进程还要继续相应客户端的命令,如果客户端输入了写操作的命令,修改n=20,此时父进程就会申请一块新空间存储n=20,子进程的n还是等于10,并且跟父进程也不是共享一块空间了
- 根据结果来说,就是子进程只会拥有fork()调用之前的所有数据。
- fork()调用之后,子进程遍历当前内存所有的数据,按照RDB文件的格式,将数据写入一个临时文件
- 写入完成之后,再把这个文件重命名为dump.rdb,替换原来旧的RDB快照文件
1.3 实际执行
先查看dump.rdb详情信息,inode是800816,文件内部的信息如下


我们现在一个客户端上设置三个键值对,此时我们去另一个客户端查看一下快照文件

可以看到dump.rdb的详情信息,他的inode此时是802428,和之前相同,可见并没有把我们直接设置的键值对储存起来,这是因为我们还没有满足自动触发rdb的条件


此时我们手动触发rdb

再去查看一下快照文件的信息,发现inode已经和之前不同了,说明确实进行了快照文件的替换

我们进入文件查看,发现里面确实存储了我们之前设置的键值对
我们再设置一个key4键值对

设置完后我们进入rdb快照文件,里面仍只有三个键值对,并没有我们刚刚设置的key4
此时我们退出客户端,重新启动redis服务,再进入客户端,发现key4竟然还是保存的
我们再进入rdb文件,发现key4保存在文件中了
说明,自动触发rdb快照除了配置redis.conf文件,在重新启动服务器的时候,redis也会自动触发rdb机制,保存快照文件
上述重启redis服务器的方式是正常关闭服务器的方式,我们再试一下非正常关闭服务器
先设置键值对key5

然后进行查看redis服务的进程号

直接使用kill -9命令删除进程,这样属于非正常关闭,我们再进入redis客户端,发现key5并没有存储成功
1.4 RDB的优缺点
优点
- RDB是一个二进制文件,代表Redis在某个时间点上数据快照,非常适用于备份等场景
- Redis加载RDB恢复数据远远快于AOF的方式
缺点
- RDB存储数据没有办法做到实时持久化,上述提到的自动触发RDB也是有时间限制的,满足一段时间内固定次数修改才会触发RDB,那么如果还未触发之前服务器就挂了,这段时间内我们的数据就丢失了
- RDB文件使用特定二进制格式保存,Redis版本演进过程中有多个RDB版本,兼容性会有风险
二、AOF
AOF持久化是以独立日志的方式记录每次写命令,AOF文件是文本文件,重启时再重新执行AOF文件的命令达到恢复数据的目的。相比于RDB一段时间记录数据,AOF解决了数据持久化的实时性,目前已经是Redis持久化的主流方式。如果将RDB比作是照片,记录了十点和十一点两张照片,那么AOF就是摄影,拍摄了十点到十一点一个小时的内容,所以保证了实时性
2.1 开启AOF
同样要在redis.conf里配置,这里默认是no未开启,我们把no改成yes,此时就开启AOF


AOF的日志命名是"appendonly.aof",和之前的dump.rdb同样在var/lib/redis文件中
修改完配置后我们要进行重启Redis服务,我们再进入文件夹,就能查看到aof的文件了

我们查看文件,可以按到我们之间的数据被记录在aof

2.2 AOF文件写入
当我们引入AOF之后,Redis又要在内存中写数据,又要把数据写入硬盘里的AOF文件,这样速度不会降低吗?
实际上没有影响,AOF机制并非直接把数据写入硬盘,而是写入内存中的缓冲区aof_buf,积累一段时间后再统一写入硬盘
缓冲区的刷新策略

我们可以在redis.conf文件中配置刷新策略
always频率最高,数据可靠性最高,性能最低
everysec频率中等,数据可靠性会降低,性能会提高
no频率最低,数据可靠性也是最低的,性能是最高(这是依靠操作系统进行刷新缓冲区)
2.3 AOF重写机制
AOF会把每个命令追加到AOF文件中,这样AOF文件就会持续增长,体积越来越大,那么就会影响到redis下次启动读取文件的时间,所以AOF有一个重写机制
已知AOF会记录所有的命令操作,比如
set key 111
set key 222
set key 333
这三条命令其实是冗余的,其实最后结果就是set key 333,所以我们只保留最后一条命令即可,也就是只针对最后的结果,剔除一些冗余的操作,从而达到给aof文件瘦身的效果
手动触发:调⽤ bgrewriteaof 命令。
⾃动触发:根据auto-aof-rewrite-min-size 和 auto-aof-rewrite-percentage 参数确定⾃动触发时机
- auto-aof-rewrite-min-size:表⽰触发重写时 AOF 的最⼩⽂件⼤⼩,默认为 64MB
- auto-aof-rewrite-percentage:代表当前 AOF 占⽤⼤⼩相⽐较上次重写时增加的⽐例
2.4 AOF重写的流程

当我们调用bgrewriteaof命令后
父进程就会调用fork(),会创建一个子进程,子进程拥有父进程的数据
在这期间父进程仍然会收到客户端的命令,这些命令会同时写入到aof_buf和aof_rewrite_buf两个缓冲区,aof_buf是上面aof机制的常规缓冲区,aof_buf里缓冲区的数据还是按照everysec策略写入到旧的AOF文件,aof_rewrite_buf是重写时的缓冲区
子进程会在内存中,遍历所有的数据,将数据写入到新创建的AOF文件
子进程写入完成之后,父进程会把aof_rewrite_buf缓冲区里重写时收到的命令再追加到新的AOF文件里
最后用新的AOF文件替换旧的AOF文件
这里最后要用新的AOF文件替换旧的AOF文件,那为什么还要把数据写入旧的AOF文件呢?
因为如果重写的新的AOF文件出现错误,最后并没有成功实现替换,这样重写时父进程收到的命令就会都丢失,所以旧的AOF文件同样得要写入数据,防止数据丢失
2.5 混合持久化
AOF是按照文本的方式来写入文件,这样后续加载的成本是比较高的,所以redis引入了"混合持久化"的方式,结合了rdb和aof的特点
混合持久化就是按照aof的方式,将每个操作记录到aof文件里,触发aof重写之后,就会把内存状态按照rdb的二进制格式写入到新的aof文件,后续的操作仍然是按照aof文本的方式追加到文件中
2.6 数据恢复
RDB和AOF都开启的时候,是读取RDB文件还是AOF文件呢?

Redis首选AOF文件,如果AOF文件存在就加载这个文件,加载成功就启动成功,如果AOF文件不存在就去加载RDB文件,这是因为AOF文件是实时性备份,数据比RDB更加全,所以首选AOF