Bootstrap

彻底理解Redis的持久化方式

一.由来

因为Redis之所以能够提供高效读写的操作,是因为它是基于内存的,但是这样也会带来一个问题,及在服务器宕机或者重启的情况下,内存里面的数据就会被丢失掉,所以为了解决这个问题,Redis就提供了持久化的技术,来保证数据的持久性和可靠性。

二.持久化方式介绍

如图: 

1.RDB持久化:在指定的时间间隔内将内存种的数据集(二进制序列化形式)快照写入磁盘,每次都是从Redis里面生成一个快照进行全量备份,也就代表我们当前时刻,Redis里面有多少数据,只要触发了RDB方式,就会将所有的数据以二进制的形式存储到磁盘里面;

2.AOF持久化:对每条写入命令作为日志,以追加(append-only)的模式写入一个日志文件中,这就代表客户端提交过来的每一个Set命令都会存储到一个文件里面进行保存,在Redis重启的时候,可以通过回放AOF日志中的写入指令来重新构建整个数据集,以达到恢复数据的效果。

三.RDB持久化流程

如图:

1.首先主进程会fork一个子进程来进行备份;

2.子进程会将共享的内存数据写到一个临时的RDB文件,而不是直接写到已经存在的这个RDB文件里面;

3.当子进程把Redis的所有数据都写到临时文件以后,就会用这个临时文件替代已经存在的RDB文件

4.在整个的备份过程中,主进程不参与这个IO操作,它可以继续支持处理客户端的请求,但是需要注意主进程,主进程此时处理请求是基于一个新的内存副本来进行操作的,而这个内存副本是通过一个叫做COW的机制来进行处理的,比如说客户端提交了一个Key过来之后,那么COW机制就会将这个Key从共享内存拷贝到这个内存副本里面,那么主进程在进行处理的时候,它就是针对这个内存副本里面的Key的副本来进行操作的,它并不是基于共享内存来进程操作的。

COW机制:

Copy-On-Write(写时复制),该机制是一种用于优化并发访问的数据结构实现策略,特别适用于读多写少的场景,COW的基本思想是在进行写操作时,不直接修改原数据,而是先复制一份副本,然后在副本上进行修改;写操作完成后,再将副本替换为原数据(这个替换操作是原子性的,以确保在任何时刻,所有读取操作都能读取到一致的数据),这样可以确保读操作与写操作之间不会相互干扰,从而提高并发性能。

注意点:

1.平时说的周期性的来进行数据备份,其实就是fork子进程的间隔时间,当然这个fork子进程备份这个过程也可以通过手动触发,像bgsave、save命令都可以进行手动触发备份的过程;

2.fork子进程的备份,它其实也是有一个自动配置的,也是通过一个配置触发的,有一个命令叫做Save *** ***(save多少秒多少个),这就代表在这个多少秒里面有多少个Key被修改了,它就会自动fork一个子进程来进行备份。

四.AOF持久化流程

如图: 

1.Redis先将这个写命令写入到一个缓存区里面,不是直接写到日志文件中;

2.当写到这个缓冲区后,才会进行一个同步刷盘的操作,这个刷盘操作是通过一个配置来进行调配的,一共有三种选项:

(1)实时同步,当客户端每来一个数据,都会将它写到日志文件中里面;

(2)设置时间间隔,通常我们会设置1s,这就代表每隔1s这个缓存区就会将数据刷盘到日志文件里面;

(3)缓冲区不会主动将数据刷盘到日志文件中,而是由系统来进行调配,那么这个方法就可能会出现RDB那种将大部分数据同时丢失的问题。

如果采用设置间隔时间为1s,这代表最多就会丢失1s的数据,同时也不会出现性能浪费,如果采用实时同步的话,那还不如直接把数据写入日志文件里面,何必中间再借助一个缓存区呢。

3.当所有数据都存在日志文件中后,AOF还提供了一个日志重写的功能,它其实就是正对AOF文件进行瘦身,比如用户针对key1进行了3此更新,在这个日志文件中,其实有效的命令只是最后一条更新,前面两次更新的命令都是冗余命令,而这个重写功能,会将前面两个冗余的命令干掉,只留下这个有效的set命令,然后这个日志文件就瘦身下来了。

4.Redis重启的时候就加载这个日志文件来恢复数据,也就是将这些命令从上往下一个一个的执行,但是这种方式,就相比于RDB加载二进制数据的方式要慢很多。

 五.优缺点

优点:

1. 性能高:因为它是二进制的形式将当前Redis里面的所有数据存在磁盘中,也就是代表当Redis重启之后,它可以直接加载这个二进制数据进行恢复,这个速度是非常快的,也就代表性能是非常高的;

2.文件紧凑:其实也是基于二进制而言的,它相比于AOF将所有的写命令进行处理,它的文件内容是相当紧凑的;

缺点:

可能丢失数据:其实这就是根据我们这个配置触发这个fork子进程备份数据的这个过程中,可能会有一点时间间隔,那比如说我们配置了3000ms 3000个key被修改,才会触发fork子进程,那就代表在上一次触发这个备份的过程中(还没备份完),如果说还没有来得及触发下一次备份的话,在这个过程中,如果出现了宕机或者重启的操作,那就代表当前时间中内存变更的数据都会被丢失,因为它还没有来的及备份。

优点:

数据更加可靠:因为AOF记录了每个写数据的操作,因此它在出现故障的时候可以通过读取AOF的日志文件逐个来进行恢复数据,同时它基于这种追加的方式把所有的set的命令都保存下来了,就可以用它来回放过去所有的些操作;

缺点:

1.文件较大:因为它存储了所有的set命令,所以通常AOF文件体积要比RDB文件要大

2.恢复数据较慢:因为它需要将AOF里面所有的set命令加载出来逐个的读取,而且当我们这个文件非常大的时候,它的加载也会非常损耗性能,所以它比RDB方式要慢很多。

六.如何选择

1.如果能够接受一段时间的缓存数据丢失,选择RDB;

2.如果是对缓存数据的实时性要求比较高,选择AOF;

但是一般情况下建议不要单独使用某一种持久化机制,而是应该两种一起用,在这种情况下,,当Redis重启的时候会优先载入AOF文件来恢复原始的数据(Redis默认优先使用AOF,相当于RDB做冷备,AOF做热备),因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。

;