redis中持久化策略
1.持久化是什么
在前面的过程中讲述了有关于MySQL中事务的一些特性以及隔离等级。其中很重要的一条就提到了持久化,持久化就是可以将数据进行一个持久保存的意思。也就是将数据写入到硬盘中,虽然,redis是操作内存的一个数据库,但是在每一次的操作中,比如往redis中写入一个数据,此时不止会在内存中进行一个操作,还会在电脑的硬盘中对相应数据做出一个备份。但平时的操作主要还是在内存中进行一个操作。但是,既然都涉及到往硬盘中写入数据了,肯定和redis快的特性在逻辑上是有一点不符的,所以我们介绍redis中的持久化策略
2.RDB
缩写为 Redis DataBase
定期备份,也就是Redis定期把内存中所有的数据给写入进硬盘,生一个一个"快照",下一次重启服务器之后,根据刚才生成的快照,将服务器的数据进行一个恢复
定期备份时间,手动备份redis中定期备份一种是 自动备份,一种是手动调用客户端中的 save和bgsave方法进行一个备份
但是在执行save的过程中,redis会尽可能的去生成一份快照,就会阻塞其他客户端的命令。所以这个操作是有一定风险的. 不太推荐使用
这里是redis配置文件中的操作:save seconds times 在规定时间之后 修改多少次才执行sava操作 比如save 60 10000 在60秒之后,同时还要修改1w次才进行一个保存,两个条件必须要同时满足 但是也有可能 在系统还没来得及备份的时候redis服务器就崩了,此时的解决方式就是我们后面讲的AOF,但也不能完全针对这个问题进行一个解决,同时系统配置文件也会在我们退出redis程序的过程中自动执行save命令(正常关闭),但是如果是异常重启,比如服务器直接挂掉,就会丢失未来得及登记快照的数据。
。
bg background bgsave是让redis在后台进行一个快照的生成,不会阻塞其他的线程的任务
bgsave执行过程
bgsave在创建快照的过程中,会现在操作系统中进行一个判断,判断是否已经有子进程在进行bgsave的操作了,要是有子进程已经在执行bgsave,则当前进程会直接进行返回,要是没有进程在进行bgsave操作的话,此时就会通过fork的方式来进行一个进程的创建, fork是linux系统提供的一个进程创建的api, fork的创建也很简单粗爆,直接把当前父进程的进程复制一份,一旦复制完成就是2个独立的进程了,也就能各种执行各自的任务了。
复制的过程中会复制 pcb 虚拟地址空间(内存中的内容) 文件描述符表 因此子进程和父进程中内存内容是相同的,此时让子进程去进行一个持久化,就等于把父进程的数据进行持久化了 父进程打开一个文件之后,会在内存中创建一个文件描述表的数据结构,子进程也会复制这个数据描述表,然后子进程也能使用父进程所打开的文件。 拷贝过程中采用的是“写时拷贝" 所以拷贝时并不会有很大开销的。
redis是单线程模型,但是此处redis是通过多进程的方式来完成并发编程的
自动备份 可以在redis的配置文件中配置每隔多长时间/每修改多少次数据就进行一次数据的修改。
3.AOF
缩写为Append Only File
实时备份
会把用户的每一个操作都存储进入文件中,而不是保存具体的内容。并且开了AOF之后 RDB 就不生效了,按照AOF为准,启动的时候就不如读取RDB文件了
AOF进行持久化的操作,虽然会进行一个硬盘的写入,但对处理请求的速度,其实并没有太大影响的,因为在进行写入前,每一个操作都会进入一个缓冲区,直到缓冲区中内容达到一定量之后,才会统一的写入进硬盘中。大大的降低了写入硬盘的次数。
但是呢只要系统是非正常退出的,缓冲区的数据未来得及写入到硬盘上,然后程序又给挂掉了,此时缓冲区的数据也是会丢失的,所以说,在redis中,为我们提供了一些缓冲区的刷新策略。
- 缓冲区刷新越快,性能影响也就越大,数据可靠性也就越高
- 缓冲区刷新越慢,性能影响也就越小,但数据可靠性会降低很多
随着AOF文件的增长,会增加redis的启动时间,因为redis启动之前会读取AOF文件,同时在AOF文件中,有很多的内容都是冗余的。
比如用户在redis中插入一个列表
- lpush key 111
- lpush key 222
- lpush key 333
其实等同于下面一个操作
- lpush key 111 222 333
AOF记录的是中间的整个过程,但是redis关注的是最终的一个结果。
所以在redis中存在一个重写机制,来整理其中的冗余操作,从而达到给AOF文件瘦身的一个效果
AOF重写触发的时机
AOF和RDB类似,触发重写的时机分为手动调用和自动执行
手动调用 输入 bgrewriteaof
自动执行 在配置文件中进行配置
自动重写AOF的过程中,系统也会创建出一个子进程。
并且在重写AOF的过程中,系统不需要关心原来的AOF中都有什么,只需要将现有数据按照AOF的格式进行重写就行了。
但是在父进程进行fork操作的时候,子进程负责进行AOF文件的重写,但是在子进程重写AOF文件的过程中,父进程还是会接受很多很多的请求的,这时的子进程是没办法实时获取到这些新增请求的,所以,父进程会在此时创建一个 aof_rewrite_buf的缓冲区,专门用来接受fork之后的请求AOF,在收到子进程已经成功重写AOF的消息时父进程在把aof_rewrite_buf的内容重新写入到新AOF文件中
要是在执行bgrewriteaof发现有子进程在执行创建快照的操作,则会进行一个等待,等快照创建完成在进行AOF的重写
要是在子进程重写AOF文件后,新AOF文件会取代旧文件,父进程依然往旧文件写入数据是否还有必要吗?这里还是非常有必要的 如果在写一半的过程中 服务器给挂掉了,子进程内存中的数据会丢失新的AOF文件还不完整。
总的来说
具体那种备份还是得看具体的场景,因为AOF实时备份会有更多的开销,但是在现在计算机硬件的配置下AOF应该比RDB多一些。