Redis的持久化:RDB与AOF

最近在博客中加了访客记录功能,将访客的信息使用redis队列记录,一个小时入一次库。但是有次我不小心重启了服务器,导致一个小时内的访客数据全部丢失,所以特地去学习了一下Redis持久化这方面的配置,防止以后再出现这种问题。

将Redis的数据从内存中以某种形式同步到硬盘中,这一操作成为Redis的持久化。Redis支持两种方式的持久化,一种是RDB,另一种是AOF。这两种方式可以单独使用也可以一起使用。

RDB持久化:

RDB方式持久化是通过快照实现,当符合参数设置的条件时Redis会自动将内存中的数据进行快照并存储在硬盘上。设置快照的条件由两个参数构成:时间和改动的键的个数。当在指定时间被被改动的键的个数大于被指定的数值时就会进行快照。RDB方式时Redis默认的持久化方式,在配置文件中已经预设置了3个条件

save 900 1      //900S内有1个键被更改
save 300 10     //300S内有10个键被更改   
save 60 10000   //60S内有10000个键被更改

save指定了快照条件,可以有多个save的存在,他们之间是“或”的关系,当满足3个条件中任意一个时,Redis都会产生快照,并将快照存储在当前目录的dump.rdb文件中,可以通过dir和dbfilename两个参数来指定快照的存储路径与文件名。

RDB快照的实现过程:1、Redis使用fork函数复制出一份子进程   2、父进程继续接受并处理客户端发来的数据,子进程则开始将内存中的数据写入硬盘中的临时文件  3、当子进程写完所有数据后会用该临时文件替换掉旧的RDB文件,至此一次快照操作完成

除了自动快照外,我们还可以通过SAVE和BGSAVE两个命令让Redis主动执行快照。但前者是由主进程执行快照操作,会阻塞住其他的请求。而后者则会通过fork子进程完成快照操作

AOF持久化:

通过RDB实现持久化,一旦Redis异常退出,就会丢失最后一次快照以后更改的所有数据,如果数据很重要,无法承受任何的丢失,可以通过AOF的方式来进行持久化


Redis默认是不开启AOF方式进行持久化的,我们可以在配置文件中通过appendonly参数来开启

appendonly yes

开启了AOF之后,redis每执行一条更改数据的命令的同时会将这条命令写入硬盘中的AOF文件中。AOF文件保存的位置与RDB文件相同,默认文件名为appendonly.aof

AOF实现的过程:假设开启AOF后客户端执行了4条命令

set foo 1
set foo 2
set foo 3
get foo

Redis会将前3个对键有更改的命令以原始通信协议包的形式记录在AOF文件中。

但是这里有一个问题:这3条被记录的命令有2条是冗余的,因为前两条的结果会被第三条覆盖。随着执行的命令越来越多,AOF文件也会越来越大,但实际内存中可能并没有多少数据。我们这里可以通过下面这个两个参数来优化这个问题

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

第一个参数的意义是当前的AOF文件的大小超过上一次重写时的AOF文件的大小的百分之多少时会进行再次重写。

第二个参数限制了允许重写的最小AOF文件大小。

除了自动重写外,我们还可以通过使用BGREWRITEAOF命令手动执行AOF重写。重写后的AOF文件会删除掉源文件中冗余的数据。

另外AOF方式值得注意的就是虽然每次执行更改数据库内容的操作时,AOF都会记录在AOF文件中,但是由于操作系统的缓存机制,数据并没有真正的写入硬盘。而是进入了系统的硬盘缓存。默认情况下系统30S执行一次同步操作,将硬盘缓存中的数据真正的写入硬盘。如果这30S中系统异常退出会导致硬盘缓存中的数据丢失。这对启用AOF方式的应用是无法接受的。所以这里就需要Redis在写入AOF文件后主动要求系统将缓存内容同步到硬盘。我们可以通过appendfsync参数来设置同步时机

# appendfsync always
appendfsync everysec
# appendfsync no

该参数可以有3个值:always, everysec, no 分别表示每次执行命令都同步一次,每秒同步一次,不同步由操作系统自动进行同步操作。一般选用everysec是最合适的,即照顾性能又保证安全


书山有路勤为径 学海无涯苦作舟