✨ Redis持久化
- Redis持久化概述
- 快照(Snapshot或RDB)
- 特点
- 备份的执行
- Fork
- 配置文件
- Redis快照的触发
- save指令(手动进行保存)
- bgsave指令
- 服务器配置自动触发
- RDB三种启动方式对比
- RDB的优缺点
- AOF
- AOF概述
- AOF写数据的三种策略(appendsync)
- AOF重写
- AOF重写原因以及作用
- AOF重写规则
- AOF重写方式
- AOF重写原理
个人主页:不断前进的皮卡丘
博客描述:梦想也许遥不可及,但重要的是追梦的过程,用博客记录自己的成长,记录自己一步一步向上攀登的印记
个人专栏:微服务专栏
参考了黑马和编程不良人的视频
1️⃣在生活中,有时候我们在写文档的时候,可能遇到断电的情况,如果数据就这样消失了,我们肯定很崩溃,毕竟自己写了那么久,所以为了防止数据的意外丢失,我们要对数据进行持久化。
2️⃣持久化:利用永久性的存储介质对数据进行保存,在特定的时间把保存的数据进行恢复的工作机制叫做持久化
3️⃣client redis[内存] -----> 内存数据- 数据持久化–>磁盘
4️⃣Redis官方提供了两种不同的持久化方法来将数据存储到硬盘里面分别是:
- 快照(RDB):保存当前数据状态,快照形式,存储数据结果,存储格式简单,关注点在数据
- AOF (Append Only File) 只追加日志文件,把数据的操作过程进行保存,日志形式,存储操作过程,存储格式复杂,关注点在数据的操作过程
这种方式可以在指定的时间间隔内把内存中的所有数据集快照都写入硬盘中,当然这也是redis的默认开启持久化方式,保存的文件是以.rdb形式结尾的文件因此这种方式也称之为RDB方式,它恢复的时候是把快照文件直接读取到内存里面。
Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到 一个临时文件中,等到持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。 整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能。 如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。
那么为什么要这样做呢?为什么不直接存到dump.rdb,而是要先存储到临时文件中呢?假如数据直接同步到dump.rdb,如果这个时候服务器挂掉了,可能有些数据就缺失了,所以我们先把数据同步到临时文件,这样是为了保证数据的完整性。
接下来说明一下怎么对rdb进行备份
1️⃣先通过config get dir 查询rdb文件的目录
将*.rdb的文件拷贝到别的地方
2️⃣关闭redis
3️⃣把备份的文件拷贝到工作目录下 cp dump2.rdb dump.rdb
4️⃣启动Redis, 备份数据会直接加载
Fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等) 数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程
在Linux程序中,fork()会产生一个和父进程完全相同的子进程,但子进程在此后多会exec系统调用,出于效率考虑,Linux中引入了“写时复制技术”
一般情况父进程和子进程会共用同一段物理内存,只有进程空间的各段的内容要发生变化时,才会将父进程的内容复制一份给子进程。
配置文件在etc/redis.conf中,在redis.conf中配置文件名称,默认为dump.rdb
配置文件中默认的快照配置如下图
rdb文件的保存路径,也可以修改。默认为Redis启动时命令行所在的目录下
客户端还可以使用SAVE命令来创建一个快照,接收到SAVE命令的redis服务器在快照创建完毕之前将不再响应任何其他的命令
save指令工作原理
save指令会阻塞当前redis服务器,一直到RDB过程完成为止,这样子可能导致长时间阻塞。
bgsave指令是手动启动后台保存操作,但是不是马上执行
客户端可以使用BGSAVE命令来创建一个快照,当接收到客户端的BGSAVE命令时,redis会调用fork¹来创建一个子进程,然后子进程负责将快照写入磁盘中,而父进程则继续处理命令请求。
名词解释: fork当一个进程创建子进程的时候,底层的操作系统会创建该进程的一个副本,在类unix系统中创建子进程的操作会进行优化:在刚开始的时候,父子进程共享相同内存,直到父进程或子进程对内存进行了写之后,对被写入的内存的共享才会结束服务
通过save second changes指令可以进行设置
当满足在一定时间内,key的变化数量达到指定数量就会进行持久化
如果用户在redis.conf中设置了save配置选项,redis会在save选项条件满足之后自动触发一次BGSAVE命令,如果设置多个save配置选项,当任意一个save配置选项条件满足,redis也会触发一次BGSAVE命令
当redis通过shutdown指令接收到关闭服务器的请求时,会执行一个save命令,阻塞所有的客户端,不再执行客户端执行发送的任何命令,并且在save命令执行完毕之后关闭服务器
因为服务器配置自动触发的方式其实本质是bgsave,所以我们看save和bgsave的对比就可以了。
方式 | save | bgsave |
---|---|---|
读写 | 同步 | 异步 |
阻塞客户端指令 | 是 | 否 |
额外内存消耗 | 否 | 是 |
启动新进程 | 否 | 是 |
RDB的优点
1️⃣RDB是一个紧凑压缩的二进制文件,存储效率高
2️⃣RDB内部存储的是redis在某个时间间隔的数据快照,适合用户数据备份,全量复制,大规模数据恢复等场景,对数据完整性和一致性要求不高的话更适合使用
3️⃣RDB恢复数据的速度比AOF快很多
RDB缺点
1️⃣RDB可能会丢失数据
2️⃣bgsave指令每次运行都要执行fork创建子进程,这样会牺牲一些性能
3️⃣Redis不同版本之间没有对RDB文件格式的版本进行统一,可能导致不同版本服务间的数据格式不能兼容
4️⃣RDB基于快照思路,每次读写都是全部数据,数据量的时候,效率低
在前面我们已经学习了RDB,并且知道了它的一些弊端,那么我们有没有什么方法可以进行改善呢?RDB每一次读写都是全部数据,而且可能丢失记录。我们可以想办法,不记录全部数据,而是对所有操作进行记录,而且仅仅记录部分数据,这样既可以排除丢失数据的风险,又可以提升效率
AOF概念:
- AOF(append only file)持久化:以独立日志的方式来记录每一次的写命令,重启的时候重新执行AOF文件中的命令,达到恢复数据的目的
- AOF主要是为了解决数据持久化的实时性,目前是redis持久化的主流方式
- 这种方式可以将所有客户端执行的写命令记录到日志文件中,AOF持久化会将被执行的写命令写到AOF的文件末尾,以此来记录数据发生的变化,因此只要redis从头到尾执行一次AOF文件所包含的所有写命令,就可以恢复AOF文件的记录的数据集.
AOF写数据过程
当客户端发送命令给服务器的时候,服务器接收到命令的时候,并没有马上记录,而是把它放到一个临时区域,这个区域就是AOF它要操作的那些写命令对应的存储缓冲区,到一定阶段以后,就会把这些命令同步到.aof文件中。但是我们可能会对一些问题有疑惑,每一次要写多少命令,多长时间把这些命令同步到AOF文件中呢?AOF中提供了三种写数据策略,帮助我们把这些命令同步到AOF文件中,接下来就开始介绍。
如果把这6条指令都记录到AOF中,那么在恢复的时候,如果去执行三个set指令其实是没有意义的,因为,我们可以看出来,其实本质上只有最后一条set指令生效,而对于incr指令来说,他们只是给原来数据进行增加或减少操作,我们也没有必要把这个指令都记录下来,我们可以用一条set指令来替代这三个incr指令
✔️AOF重写原因
我们知道随着命令的不断执行,AOF里面的文件也会变得越来越大,但是其实有一些命令其实是多余的,我们可以用等效命令来执行,也就是对于同一个数据的多个操作命令的执行结果,我们可以转换成为数据最终的结果对应的指令来进行记录。
Redis引入AOF重写机制来压缩文件体积,AOF重写是把Redis进程内的数据转化为命令同步到新AOF文件的过程。
✔️AOF重写的作用
1️⃣降低磁盘占用量,提高磁盘利用率
2️⃣提高持久化率,降低持久化写时间,提高IO性能
3️⃣降低数据恢复所用时间,提高数据恢复效率
# 1.客户端方式触发重写
- 执行BGREWRITEAOF命令 不会阻塞redis的服务
# 2.服务器配置方式自动触发
- 配置redis.conf中的auto-aof-rewrite-percentage选项 参加下图↓↓↓
- 如果设置auto-aof-rewrite-percentage值为100和auto-aof-rewrite-min-size 64mb,并且启用的AOF持久化时,那么当AOF文件体积大于64M,并且AOF文件的体积比上一次重写之后体积大了至少一倍(100%)时,会自动触发,如果重写过于频繁,用户可以考虑将auto-aof-rewrite-percentage设置为更大
注意:重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,替换原有的文件这点和快照有点类似。
重写流程