redis提供了两种不同的持久化方法来将数据存储到硬盘里面。一种方法叫快照,它可以将存在于某一时刻的所有数据都写入硬盘里面。另一种方法叫只追加文件(AOF),它会在执行写命令时,将被执行的写命令复制到硬盘里面。这两种持久化方法既可以同时使用,又可以单独使用,在某些情况下甚至可以两种方法都不用,具体选择哪种持久化方法,需要根据用户的数据及应用来决定。

快照持久化

redis可以通过创建快照来获得在内存里面的数据在某个时间点上的副本。在创建快照之后,用户可以对快照进行备份,可以将快照复制到其他的服务器从而创建具有相同数据的服务器副本,还可以将快照留在原地以便重启服务器使用。

快照的配置如下:



save 60  1000
stop-srites-on-bgsave-error no
rdbcompression on
dbfilename  dump.rdb



创建快照的几种方法:

  1. 客户端可以通过向redis发送bgsave命令来创建一个快照。对于支持bgsave命令的平台来说(除windows外),redis会调用fork来创建一个子进程,然后子进程负责将快照写入硬盘,二父进程继续处理命令请求。
  2. 客户端还可以通过性redis发送save命令来创建一个快照,接到save命令的redis服务器在快照创建完毕之前将不再响应其他任何命令。save命令并不常用,我们通常只会在没有足够内存去执行bgsave命令的情况下,又或者即使等到持久化操作执行完毕也无所谓的情况下,才会使用这个命令。
  3. 如果用户设置了save配置选项,譬如save 60 10000, 那么从redis最近一次创建快照操作之后开始算起。当“60s内有10000次写入”这个条件被满足时,redis就会自动触发bgsave命令。如果用户设置了多个save配置选项,那么当任意一个save配置选项所设置的条件被满足时,redis就会触发一次bgsave命令。
  4. 当redis通过shutdown命令接收到关闭服务器的请求时,或者接受到标准term信号时,会执行一个save命令,阻塞所有客户端,不再执行客户端发送的任何命令,并在save命令执行完毕之后关闭服务器。
  5. 当一个redis服务器连接另一个redis服务器,并向对方发送sync命令来开始一次复制操作的时候,如果主服务器目前没有在执行bgsave操作,或者主服务器并非刚刚执行完bgsave操作,那么主服务器就会执行bgsave命令。

在只使用快照持久化来保存数据时,一定要记住:如果系统真发生崩溃,用户将丢失最近一次生成快照之后的更改的所有数据。因此,快照持久化只适用于那些即使丢失一部分数据也不会造成问题的应用程序。

AOF持久化

简单来说,AOF持久化会将被执行的写命令写到AOF文件的末尾,以此来记录数据发生的变化。因此,redis只要从头到尾重新执行一次AOF文件包含的所有写命令,就可以恢复AOF文件所记录的数据集。AOF持久化可以通过设置如下选项来打开。



appendonly  no                                 #是否开启aof持久化
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size  64mb

dir  ./                                       #这个参数决定来持久化文件保存的位置

appendfsync参数有三个选项:

always: 每个redis写命令都要同步写入硬盘,这样会严重降低redis的速度。
everysec: 每秒执行一次同步,显式地将多个写命令同步到硬盘。
no : 让操作系统来决定应该何时进行同步。


如果使用always选项的话,那么每个redis写命令都会被写入硬盘。从而将发生系统崩溃时出现的数据丢失减少到最少。不过遗憾的是,因为这种同步策略需要对硬盘进行大量写入,所以redis处理命令的速度会受到硬盘性能的影响;机械硬盘在这种同步频率下每秒只能处理大约200个写命令,而固态硬盘每秒大概也只能处理几万个写命令。(使用固态硬盘慎用always选项,因为不断写入少量数据做法可能会引发严重的写入放大问题)。

为来兼顾数据安全和写入性能,可以考虑用everysec选项,让redis以每秒一次的频率对aof文件进行同步。redis每秒同步一次aof文件时的性能和不适用任何持久化特性时的性能相差无几,而通过每秒同步一次aof文件,redis可以保证,即使出现系统崩溃,用户也最多只会丢失一秒之内产生的数据。当硬盘忙于执行写入操作的时候,redis还会优雅地放慢自己的速度以便使用硬盘的最大写入速度。

如果使用来no选项,那么redis将不对aof文件执行任何显式的同步操作,而是由操作系统来决定应该在何时对aof文件进行同步。这个选项在一般情况下不会对redis的性能带来影响,但系统崩溃将导致使用这种选项的redis服务器丢失不定数量的数据。另外,如果用户的硬盘处理写入操作的速度不够快,那么当缓冲区被等待写入硬盘的数据被填满时,redis的写入操作将会被阻塞,并导致redis处理命令请求的速度变慢。

虽然aof持久化非常灵活地提供来多种不同的选项来满足不同应用程序对数据安全的不同要求,但aof持久化也有缺陷,那就是aof文件的体积大小。

重写/压缩AOF文件

redis会不断地将被执行的写命令记录到aof文件里面,所有随着redis不断运行,aof文件的体积也会不断增长,在极端情况下,体积不断增大的aof文件甚至可能会用完硬盘的所有可用空间。并且,redis在重启之后需要通过重新执行aof文件记录所有写命令来还原数据集,所以如果aof文件体积非常大,那么还原操作执行的时间就可能会非常长。

为来解决aof文件体积不断增大的问题,用户可以向redis发送BGREWRITEAOF(bgrewriteaof)命令,这个命令会通过移除aof文件中冗余命令来重写aof文件,使aof文件的体积变得尽肯能小,bgrewriteaof的工作原理和bgsave创建快照的工作原理非常相似:redis会创建一个子进程,然后由子进程负责对aof文件进行重写。因为aof文件重写也需要用到子进程,所以快照持久化因为创建子进程而导致的性能问题和内存占用问题,在aof持久化中同样存在。

aof持久化可以通过设置auto-aof-rewrite-percentage选项和auto-aof-rewrite-min-size选项来自动执行bgrewriteaof。默认的配置如下:



auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

#那么当aof文件的体积大于64MB,并且aof文件的体积比上一次重写之后的体积大来至少一倍(100%)的时候,redis将执行bgrewriteaof命令。如果aof重写执行得过于频繁的话,用户可以考虑将auto-aof-rewrite-percentage选项的值设置为100以上,
#这种做法可以让redis在aof文件的体积变得更大之后才执行重写操作,不过也会让redis在启动时还原数据集所需的时间变得更长。



验证快照文件和aof文件

无论是快照持久化还是aof持久化,都提供了在遇到系统故障时进行数据恢复的工具。redis提供来两个命令行程序redis-check-aof和redis-check-dump,它们可以在系统故障发生之后,检查aof文件和快照文件的状态,并在有需要的情况下对文件进行修复。



[root@test2 redis]# redis-check-aof 
Usage: redis-check-aof [--fix] <file.aof>
[root@test2 redis]# redis-check-rdb 
Usage: redis-check-rdb <rdb-file-name>
[root@test2 redis]#



如果用户在运行redis-check-aof程序时给定了--fix参数,那么程序将对aof文件进行修复。程序修复aof文件的方法非常简单:它会扫描给定的aof文件,寻找不正确或者不完整的命令,当发现第一个出错命令的时候,程序会删除出错的命令以及位于出错命令之后的所有命令,只保留那些位于出错命令之前的正确命令。在大多数情况下,被删除的都是aof文件末尾的不完整的写命令。