Redis的持久化
1.Redis的持久化方案
由于redis的数据都存储在内存中,如果没有配置持久化,redis重启之后数据就会全部丢失,于是需要redis的持久化功能,将数据保存到磁盘中,在redis重启后,就会从磁盘中恢复数据
从严格意义上说,Redis服务提供四种持久化存储方案:RDB、AOF、虚拟内存(VM)和 DISKSTORE。虚拟内存(VM)方式,从Redis Version 2.4开始就被官方明确表示不再建议使用,Version 3.2版本中更找不到关于虚拟内存(VM)的任何配置范例
RDB:在指定的时间间隔,对内存中的数据进行快照存储,原理是将redis在内存中的数据定时dump到磁盘上的dump.rdb进行持久化
AOF:记录每一次对服务器的操作,相当于日志的形式持久化数据,原理是Redis的操作日志以追加的形式写入文件。
2.RDB
RDB 持久化是在指定时间间隔内将内存中的数据写入磁盘,实际操作过程是fork(开辟)一个子进程,先将数据集写入临时文件,写入成功之后,再替换之前的文件,用二进制压缩进行存储
讲解一下图的执行流程
1:当达到快照的条件的时候(或者手动进行触发save(堵塞,执行save期间,redis不能操作其他的指令,耗费性能,不使用)/ bgsave(执行该命令的时候,Redis后台fork一个子进程,只会在fork期间堵塞) )进行触发RDB持久化
2:redis会fork(开辟)一个子进程
3.1:子进程将redis内存区域的数据压缩到一个临时的rdb文件中,然后进行替换原先的rdb文件,完成对新数据的持久化,快照进程结束
3.2:在子进程执行的时候回copy出一个新的内存区域B,这时候操作的数据会存放在B内存中,直到快照结束的时候才会将变更写入到原始的内存中。
问题:
在进行快照操作的这段时间,如果发生服务崩溃怎么办?
在快照操作没有完成之前(临时文件没有压缩替换完成之前),原始的rdb文件是不会变更的,如果服务出现崩溃,就会用原始的rdb文件进行恢复。也就是快照子进程会创建一个临时文件进行接收压缩的数据,等待压缩完成之后才会替换原先的rdb文件。
下面是rdb配置的主要信息
# 周期性执行条件的设置格式为
save <seconds> <changes>
# 默认的设置为:
save 900 1 # 如果900秒中有1条key发生变化,开始快照
save 300 10 # 如果300秒中有10条key发生变化,开始快照
save 60 10000 # 如果60秒中有10000条key发生变化,开始快照
# 以下设置方式为关闭RDB快照功能
save ""
3.AOF
由于RDB是一定时间间隔内进行快照,对于重要的数据,RDB在发生服务器崩溃的时候常常会丢失最近一批更新的数据。如果数据非常的庞大,在快照的时候cpu会讲资源用到快照的操作上去,就会降低redis的性能
AOF方式的核心思想就是:
记录Redis服务启动成功后的每一次影响数据状态的操作命令,以便在Redis服务异常崩溃的情况出现时,可以按照这些操作命令恢复数据状态。
这样一直记录操作,AOF文件会越来越大,不会降低恢复的难度吗?
AOF提供了一种解决办法,AOF的重写 最终的目的是记录每一条数据最终的一种状态,比如我对一个key做了好多次操作,他会将每一次的操作记录到aof中,这是没有必要的,我没做持久化只是为了数据的恢复,没有必要清除数据的操作过程,那么记录数据的最终结果就可以了,这就是AOF的重写
redis的config中有这样一个参数
appendfsync:这个参数项是AOF功能最重要的设置项之一,主要用于设置“真正执行”操作命令向AOF文件中同步的策略。
什么叫“真正执行”呢?还记得Linux操作系统对磁盘设备的操作方式吗? 为了保证操作系统中I/O队列的操作效率,应用程序提交的I/O操作请求一般是被放置在linux Page Cache中的,然后再由Linux操作系统中的策略自行决定正在写到磁盘上的时机。而Redis中有一个fsync()函数,可以将Page Cache中待写的数据真正写入到物理设备上,而缺点是频繁调用这个fsync()函数干预操作系统的既定策略,可能导致I/O卡顿的现象频繁 。
appendfsync他可以设置三个值分别为 :always、everysec、no,默认的值为everysec。
always:会使得AOF对数据的保存非常稳健。其设置意义是只要有一个写操作命令执行成功,就执行一次fsync函数调用。所以很显然always的设定值,就是三个选项值中处理效率最慢的。
no:这个设置值表示Redis不会将执行成功的操作命令正真刷入AOF文件,而是完成操作系统级别的写操作后就认为AOF文件记录成功了,后续的I/O操作完全依赖于操作系统的设定,一般30秒会刷一次。
everysec:这是默认的设置值,也是可以在数据稳健性和性能上平衡较好策略。它表示每秒钟都做一次fsync函数调用,正真做AOF文件的写入操作。