RDB和AOF持久化

上片文章我们说了redis的一些简单的基础知识,接下来我们来聊一聊它是如何进行持久化的。

         redis是一个基于内存的非关系型数据库,那么基于内存那就容易丢失数据,不小心断个电,你所有的缓存数据就丢失了,redis针对持久化这个问题,提出了两套解决方案:RDB和AOF,这两个持久化方案各有优缺点,所以最后又出现了一套方案,就是将两者结合!简直完美!

一、RDB全量持久化

定义:RDB持久化的方式事实上就是利用 快照,将缓存中的所有数据存一个备份,就像我们手机相册常常提醒我们备份到云空间中,redis自动的帮我们做了这个备份操作,并且这是Redis默认开启的。

全量:因为它是将所有数据一股脑的进行快照,尽管备份过的数据,也还是会被重新保存一遍

快照后产生的数据是采用二进制形式保存的,所以占用的空间比较小。

提供命令:save、bgsave

save:是通过异步方式去执行的,但是save命令是会阻塞主进程的,因为save是按照普通命令去执行,而Redis又是单线程,若执行save指令,那redis的其他操作将会停止,在需要保存的数据量较大的时候,相当于整个redis事务停下来,等你备份完之后才能进行,这中间可能会是几秒,甚至更久。对于用户体验来说,这显然是不合适的。

bgsave:bgsave命令是对save命令的升级改善,在备份数据的时候不会阻塞主进程,Redis会再为其fork一个线程,然后叫这个线程去备份数据,然后主进程继续业务操作。

bgsave中fork一个线程进行保存操作的基本原理,其实就是将主进程中的数据,再复制一份到刚刚fork的线程中,所以占用的空间大小是save的两倍。

触发场景:

save:

  • 客户端手动发送save命令执行

  • 在Redis的shutdown状态下会自动执行

bgsave:

  • 客户端手动发送bgsave命令执行

  • Redis配置定时任务触发(支持间隔时间 + 修改数据,两者满足其一即可触发)

RDB数据恢复:

若出现断电的情况,是不会触发持久化机制的。所以会有一部分还来不及持久化的数据丢失(这部分数据量可大可小),在重启恢复阶段,redis会先去读取RDB文件内容,然后将数据写入内存中,恢复期间将不会接受任何的业务需求。

优点:在redis重启时,从磁盘读入数据速度较快、以二进制形式存储空间占用小

缺点:在redis宕机后,可能会导致大部分数据丢失,无法恢复。

二、AOF增量同步模式

AOF的基本知识

定义:AOF和RDB不同,不是直接将所有数据快照序列化到本地,而是只保存命令,将redis的每次请求命令保存在磁盘中。若遇到宕机,恢复数据到内存需要重新执行这些请求命令。

增量:是因为它并不会重复执行已经执行过的请求命令。

例如:set key 1、set key 2,最后只会执行第二个语句。

提供策略:

  • always

每次执行一次请求命令,都会触发一次写入磁盘的操作,只有写入成功之后,正确返回,才算完成。这样可以保证数据的正确性。

按照上述所说,这样的策略会极大的影响Redis的写入速度,这样每次请求一次就进行一次IO操作,丢失了Redis基于缓存的这个特点,对redis的速度有极大的削减,还不如直接用MySQL呢。

  • every sec

表示异步执行,在执行完请求命令后,再将命令放到任务队列中,由子线程异步方式将执行命令分批写入文件中,1s写入一次,断电情况下可能会丢失最后1s的执行记录,但可以大大降低对redis命令执行效率的影响。

  • no

redis不控制什么时候去写入磁盘,由操作系统去决定什么时候往磁盘flush。

很显然,这种方式非常不可取。

AOF日志数据恢复:

在重启恢复阶段,redis会先去读取AOF文件内容,然后重新执行这些请求指令,这种方式会消耗大量的时间,将数据写入内存中,恢复期间将不会接受任何的业务需求。

优点:

每次备份的时候耗时较少,不会怎么影响redis的事务执行;

数据完整性要高于RDB,在丢失数据的时,顶多就丢失1s的数据。

缺点:

宕机后,恢复数据较慢,因为要重新执行请求命令;

文件占用空间大小会逐渐增大,相比于RDB的二进制序列化存储,这种直接存储命令的方式很占空间。

AOF重写

什么是AOF重写?

比如set key 1,set key 2,这两个指令经过重写之后,就会变成set key 2。覆盖了前一个指令。

触发条件:

  • aof文件至少达到64M才会自动重写,文件大小

  • 文件自上次重写后文件大小增长100%

重写后,主进程会fork一个子进程去完成重写的操作,这样可以不影响redis的主进程运行。

AOF重写的流程大致如下:

redis在正常处理事务时,会先将请求命令放入AOF缓冲区,然后再写入磁盘到AOF文件中。

但是在发生AOF重写时,我们可以看到,redis并不是在原有的AOF文件中去重写,而是新建了一个文件

这样做的好处是可以防止重写失败不会污染原来的文件。不好之处就是会占用大量存储空间。因为要新建一个AOF文件。

在重写过程中将会出现AOF文件数据和实际的对应不上,因为在重写的过程中,redis还是会进行业务处理,所以就继续增加写入请求命令。这时为了保证 数据一致性,在重写过程中将会把在这过程中的请求命令写入到 AOF重写缓冲区 ,在重写完成,并且替换掉原文件后,再将重写缓冲区的数据写入到AOF文件中,这样就保证了不会出现数据不一致问题。

阻塞主进程的操作有哪些?

  • 将AOF重写缓冲区的数据写入AOF文件。

  • 对新建的AOF文件改名,覆盖现有的AOF文件,替换文件。

虽然以上操作会阻塞主进程,但是为了提升用户体验,① 可以设置在流量较少的时间段进行重写;② 或者使用ssd,提升持久化效率。

通过对上述RDB和AOF两种持久化方式的分析,我们可以得出,二者有利有弊,并且利弊都是相对的,所以在redis4.0开始引进了第三种方式,将二者结合起来。

RDB和AOF混合持久化(Redis4.0)

先重新回顾一下二者的缺点:

① RDB快照在持久化到磁盘中速度慢;② 若发生丢失数据,数据量可能会很大

① AOF日志恢复数据到内存速度慢;② AOF文件占用空间较大;

那怎么将二者结合呢?

        实质上使用的还是AOF文件,只不过结构发生了变化,原来的AOF文件内是记录的请求命令,新的AOF文件结构是:RDB快照数据 + AOF日志记录命令,如下图:

 

        在开始的时候,还是以日志的方式储存请求命令,达到rewrite机制的执行条件后,主进程fork一个子进程将AOF文件中的请求命令得到的数据集使用RDB快照方式转换成 二进制形式存储,然后再将AOF重写缓冲区的命令写入到新的AOF文件中,这样AOF文件中就会存放着 RDB数据AOF数据

通过上述的RDB 和 AOF 混合持久化策略,很好的将二者的优点结合在一起。

①解决AOF文件占用磁盘空间大的缺点

②解决AOF恢复数据到内存时速度慢的缺点

③解决RDB快照备份,容易丢失大量数据问题

数据恢复:

系统重建缓存会先加载RDB文件完成主体数据的重建,然后在此基础上重放AOF增量命令,大大减少了reids重建缓存数据的时间。

参考文献:

Redis缓存何以一枝独秀?(2) —— 聊聊Redis的数据过期、数据淘汰以及数据持久化的实现机制 - 掘金

你真的了解Redis的持久化机制吗? - 掘金

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值