说一说Redis的持久化机制

Redis的持久化机制,主要有2种持久化方式,即RDB持久化和AOF持久化。
问题一:为何需要进行持久化?
Redis作为内存数据库,其数据都被存储在内存中。也就是说Redis的服务器进程over或者运行载有Redis服务进程的JVM挂掉,其Redis服务器中的数据就会丢失。
为了避免这种情况发生造成的数据丢失,Redis提供了持久化机制,即将存在内存中的数据保存到磁盘中(这里和ES的默认设置有部分类似,可以对照参考),用以在上述情况发生导致数据可能丢失时,快速恢复之前的数据。
问题二:什么是RDB持久化?
RDB持久化是在某个时间点上,将Redis中的数据通过快照的方式保存到一个后缀为.rdb的RDB文件中。也由于RDB持久化是快照方式保存的性质,所以也被称为快照持久化。
通过RDB持久化所生成的文件(.rdb)其实是一个经过压缩的二进制文件,该文件可以被还原成生成RDB文件时Redis中的数据(可以理解为原路返回)。
快照持久化的原理: 创建:
1.save命令
在redis运行中,可以通过发送save命令来拍摄快照。save命令是阻塞命令,也就是当服务器接收了一条save命令之后就会开始拍摄快照,在此期间不会再去处理其他的请求,其他请求会被挂起直到快照持久化备份结束才执行被刮起的其他请求。
说一说Redis的持久化机制
文章图片
直接在当前进程执行 2.bgsave命令
bgsave命令也是立即拍摄快照,这优于save命令,bgsave并不是一条阻塞命令,而是派生出(fork)一个子线程,然后这个子线程负责备份操作。而父进程继续处理客户端的请求,这样就不会造成阻塞了。
说一说Redis的持久化机制
文章图片
在当前进程创建子线程 说到这里敲一下小黑板:
因为BGSAVE命令可以在不阻塞服务器进程的情况下执行,所以推荐使用BGSAVE命令。我们可以手动执行该命令,但还是推荐设置一下Redis服务器配置文件的save选项,让服务器每隔一段时间自动执行一次BGSAVE命令。那么可以通过save选项设置多个保存条件,只要其中一个满足条件,服务器就会执行BGSAVE命令。
说一说Redis的持久化机制
文章图片
说一说Redis的持久化机制
文章图片
SNAPSHOTTING快照 上图中,默认的配置条件表示的含义是:只要满足三者之一,BGSAVE命令就会被执行,
服务器在900s之内,对数据库进行了至少1次修改;
服务器在300s之内,对数据库进行了至少10次修改;
服务器在60s之内,对数据库进行了至少10000次修改;
也就是说,在数据操作越频繁的情况下,越需要及时的进行快照持久化操作,以确保数据的安全。
Redis载入RDB文件:
并没有专用命令,而是在Redis服务器启动时自动执行,且Redis启动时是否会载入RDB文件还取决于服务器是否启用了AOF持久化功能,具体的前值判断如下:
1.只有在AOF持久化功能处于关闭状态时,服务器才会使用默认的RDB文件来还原数据。
2.如果服务器开启了AOF持久化(默认情况下AOF是关闭的),那么服务器会优先使用AOF文件来还原数据。
3种服务器状态:
1.save命令导致的Redis服务器阻塞状态,此处不再赘述;
2.bgsave命令,Redis服务器不会被阻塞,可以继续处理客户端发来的请求;
3.在载入RDB文件期间,会一直处于阻塞,知道RDB文件载入成功。
优缺点:
优点:
1.RDB文件是一个很简洁的单文件,它保存了某个时间点的Redis数据,很适合用于做备份。你可以设定一个时间点对RDB文件进行归档,这样就能在需要的时候很轻易的把数据恢复到不同的版本。
2.RDB很适合用于灾备处理。单文件很方便就能传输到远程的服务器上。
3.RDB的性能好,进行持久化时,主进程会派生一个子进程出来,然后把持久化的工作交给子进程,自己不会有相关的I/O操作。
4.比起AOF,在数据量比较大的情况下,RDB的启动速度更快。
缺点:
1.RDB容易造成数据的丢失。假设每5分钟保存一次快照,如果Redis因为某些原因不能正常工作,那么从上次产生快照到Redis出现问题这段时间的数据就会丢失。
2.RDB使用fork()产生子进程进行数据的持久化,如果数据比较大的话可能就会花费点时间,造成Redis停止服务几毫秒。如果数据量很大且CPU性能不是很好的时候,停止服务的时间甚至会到1s。
禁用快照持久化:
1.在redis.conf配置文件中注释掉所有的save配置;
2.在最后一条save配置追加save" "命令。


三、什么是AOF持久化?
概述:
AOF持久化是通过保存Redis服务器所执行的“写”命令来记录数据库数据的,如下图:
说一说Redis的持久化机制
文章图片
默认情况下,AOF持久化功能是关闭的,如果想要打开AOF,可以修改“appendonly no”为“sppendonly yes”,如图:
说一说Redis的持久化机制
文章图片
图片采自网络 (假设Redis中还未存储任何数据,我们执行了写命令,则Redis服务器会生成1个名为“appendonly.aof”文件,该文件打开后,里边会出现刚才执行的所有写命令。)
实现AOF:
当AOF持久化功能处于打开状态时,Redis服务器在执行完写命令之后,会将被执行的写命令追加到AOF缓冲区的末尾,Redis服务器会根据配置文件中的appendfsync选项的值来决定何时将AOF缓冲区中的内容写入和同步到AOF文件里边。(appendfsync选项有以下3个值:①always---always是最安全的,即丢失数据最少,即使出现故障停机,数据库也会只丢失一个循环中所产生的命令数据;但always效率最慢,因为在每个事件循环都要将AOF缓冲区中的所有内容写到AOF文件,并且同步AOF文件。②everysec---everysec即使出现故障停机,只会丢失一秒的命令数据;且everysec足够快因为它每隔一秒就要在子线程中对AOF文件进行同步。③no---如果故障停机,数据库会丢失上一次同步AOF文件之后的所有写命令数据,至于何时对AOF文件进行同步,则由操作系统决定,所以具有不确定性,no模式和everysec效率相当。)
综上所述,我们推荐使用everysec选项,正巧appendfsync选项的默认值也是everysec,因为货比三家之后,其即安全又高效。
载入AOF:
AOF文件包含了重建数据库所需的所有写命令,所以Redis只需要重新读取并执行一次AOF文件里边保存的写命令,就可以高度还原之前的数据。步骤如下:
1.创建一个不带网络连接的伪客户端;
2.从AOF文件中提取一条写命令;
3.使用为客户端执行2中提取的写命令;
4.循环执行2、3两步骤,直至AOF文件中的所有写命令被执行完毕。
正如之前所述,如果Redis服务器开启了AOF持久化,那么会优先使用AOF(启动时载入AOF文件)而非RDB。
AOF重写:
物极必反,因为AOF持久化是通过不停追加写命令执行的数据库记录数据,所以Redis运行时间越久,AOF文件内容越多,体积增大,会出现:
1.磁盘空间被占用过多,可能会对Redis服务器甚至整个计算机造成影响;
2.AOF文件体积越大,所需要的还原数据的时间就越久。
为了避免上述情况出现,Redis提供了AOF文件重写功能,即Redis服务器会创建一个新的AOF文件来代替现有的AOF文件,新旧AOF二者保存数据相同(此处与HashMap的扩容原理部分思想相似,HashMap是通过重新生成一个数组以存放更多数据,即小桶换大桶,有兴趣可访问https://blog.csdn.net/gaobai_Siri/article/details/104412819查看HashMap扩容原理),但是新的AOF文件会省去很多浪费空间的冗余命令,所以新AOF文件体积也会大幅缩小。
重写原理:
AOF文件重写并不需要对现有的AOF文件进行任何操作,而是从现有的Redis服务器中获取当前的数据库数据来实现。如果Redis服务器中存储的键值对足够多,AOF文件重写生成的新AOF文件就会减少很多的冗余命令,进而大大减小体积。(也就是说,AOF重写就是先从数据库中读取键现在的值,然后用一条写命令去记录键值对,替换之前记录这个键值对的所有写命令。)
但是,由于AOF文件重写会进行大量的文件写入操作,所以线程将被长时间阻塞,服务器将无法处理客户端发送过来的命令请求。为了避免该情况发生,Redis将AOF文件重写功能放到子进程执行:
1.子进程对AOF文件重写期间,服务器进程(父进程)可以继续处理命令请求,
【说一说Redis的持久化机制】2.子进程带有服务器进程的数据副本,使用子进程而不是线程,可以在避免使用锁的情况下,保证数据安全。
AOF后台重写步骤:
1.服务器进程创建子进程,子进程开始AOF文件重写;
2.创建子进程的同时,父进程执行的所有写命令,要同时写入AOF缓冲区和AOF重写缓冲区(此处是为了避免新旧AOF文件保存的数据库数据不一致);
3.子进程完成AOF文件重写,向父进程发送信号,父进程收到之后,会将AOF重写缓冲区的所有内容写入新AOF文件,并对新的AOF文件进行改名,原地覆盖现有的AOF文件,完成去旧迎新。
除了手动执行BGREWRITEAOF命令外,Redis还提供了2个配置项用来自动执行该命令。
auto-aof-rewrite-percentage 100//当AOF文件的体积比上一次重写后的体积大了至少一倍(100%)时;
auto-aof-rewrite-min-size-64mb//当AOF文件的体积大于64MB时;
Redis将自动执行BGREWRITEAOF命令。


说到此处,如果要对比说明RDB和AOF持久化的区别,应该分别从实现方法、文件体积、数据安全性、优先级谈起。
1.RDB是保存数据结果,AOF保存创建数据库(写命令)过程;
2.所以RDB相对于AOF来说AOF存在体积越来越大的困扰,但是通过重写AOF文件可解决;
3.AOF持久化的安全性要比RDB高,不仅因为在机器故障时,RDB可能丢失上一次RDB持久化后写入的数据,还因为AOF最多丢失1s的写入数据(默认使用everysec的情况)。
4.优先级取决于是否开启了AOF持久化,若已开启,则AOF优先,若未开启,只能是使用Redis默认的RDB文件来还原数据。


(版权侵删)

    推荐阅读