Redis支持两种持久化方式:
(1)RDB:按照指定的规则“定期”将内存中的数据存储到硬盘上;
(2)AOF:定期或者在每次执行命令后将命令本身记录下来;
两种持久化方式可以单独使用一种,也可以二者同时使用。
一、RDB
RDB方式的持久化是通过对内存中的数据进行快照完成的,当符合一定条件时,Redis会自动将内存中的所有数据生成一份副本并存储在硬盘上。
RDB触发机制:
1、根据配置规则进行自动快照,配置文件中SNAPSHOTTING部分可设置;
2、用户执行SAVE或BGSAVE;
3、执行FLUSHALL命令;
4、执行复制(replication)时。
配置:
rdbcompression:是否在 dump .rdb 数据库的时候使用 LZF 压缩字符串,默认都设为 yes,如果你希望保存子进程节省点cpu,你就设置它为 no,不过这个数据集可能就会比较大
rdbchecksum:是否校验rdb文件,从rdb格式的第五个版本开始,在rdb文件的末尾会带上CRC64的校验和,这跟有利于文件的容错性,但是在保存rdb文件的时候,会有大概10%的性能损耗,所以如果你追求高性能,可以关闭该配置。
dbfilename:设置dump文件的名字。
dir:rdb文件输出路径。
save:save 900 1 表示在900秒内如果有一个key被操作了,就执行保存快照,可以设置多个条件,各个条件彼此之间是或的关系,如果要禁用,将条件都删除,写成save ""即可。
原理:
1、SAVE:
Save是在Redis进程中执行的,由于Redis是单线程实现,所以当save命令在执行时会阻塞Redis服务器一直到该命令执行完成为止。
2、BGSAVE:
bgsave命令会先fork出一个子进程,然后在子进程中生成RDB文件。由于在子进程中执行IO操作,所以bgsave命令不会阻塞Redis服务器进程,Redis服务器进程在此期间可以继续对外提供服务。
具体过程如下:
(1)Redis使用fork函数复制一份当前进程(父进程)的副本(子进程);
(2)父进程继续接受并处理客户端发来的命令,而子进程开始将内存中的数据写入硬盘中的临时文件;
(3)当子进程写入完所有数据后会用该临时文件替换旧的RDB文件,至此,一次快照操作完成。
在执行fork的时候,操作系统(类Unix)会使用写时复制(copy-on-write)策略,即fork函数发生的一刻,父子进程共享同一内存数据,当父进程要更改其中某片数据时(如执行一个写命令),操作系统会将该片数据复制一份以保证子进程的数据不受影响,所以新的RDB文件存储的是执行fork一刻的内存数据。
二、AOF
当使用Redis存储非临时数据时,一般需要打开AOF持久化来降低进程终止导致的数据丢失。AOF可以将Redis执行的每一条写命令追加到硬盘文件中,这一过程显然会降低Redis性能,但是大部分情况下这个影响是可以被接受的,另外可以使用较快的硬盘以提高AOF的性能。
配置:
appendonly:yes为启用AOF,no为关闭AOF
appendfilename:AOF文件名
AOF文件保存路径跟RDB文件相同,都是通过dir来设置
auto-aof-rewrite-percentage:aof自动重写配置。当目前aof文件大小超过上一次重写的aof文件大小的百分之多少进行重写,即当aof文件增长到一定大小的时候Redis能够调用bgrewriteaof对日志文件进行重写,如果之前没有重写,则以启动时的aof文件大小为依据。当前AOF文件大小是上次日志重写得到AOF文件大小的二倍(设置为100)时,自动启动新的日志重写过程。如果将百分比指定为0,则表示关闭该功能。
auto-aof-rewrite-min-size:设置允许重写的最小aof文件大小,避免了达到约定百分比但尺寸仍然很小的情况还要重写
appendfsync:aof持久化策略的配置,no表示不执行fsync,由操作系统保证数据同步到磁盘(30秒每次,数据放在Page Cache中),速度最快,但是最不安全。always表示每次写入都执行fsync,以保证数据同步到磁盘。everysec表示每秒执行一次fsync,可能会导致丢失这1s数据。dis-persistence-demystified.html,如果不确定,选择"everysec"。
RDB载入的速度要比AOF载入的快,当redis启动时,如果rdb持久化和aof持久化都打开了,那么程序会优先使用aof方式来恢复数据集,因为aof方式所保存的数据通常是最完整的。如果aof文件丢失了,则启动之后数据库内容为空。
注意:如果想把正在运行的redis数据库,从RDB切换到AOF,建议先使用动态切换方式,再修改配置文件,重启数据库。(不能直接修改配置文件,重启数据库,否则数据库中数据就为空了,因为加载的时候找不到aof文件,服务器就认为数据为空。)