Redis 持久化

727 阅读3分钟

我们知道,redis是基于内存的,也就是说数据在内存中,这也是为什么redis这么快的原因之一。但是当redis重启了,内存中的数据就会丢失。所以,redis就有持久化的机制。它提供两种方式的持久化:

  1. RDB
  2. AOF

前者根据指定的规则‘定时’将内存中的数据存储在硬盘中。后者在每次执行写命令后将命令本身记录下来。

RDB方式

当符合一定的条件的时候,redis会自动将内存中的所有数据生成一个副本并存储在硬盘上。这个过程被称为‘快照’。

根据配置规则进行自动快照

在配置文件redis.conf中, 配置save如下例:

save 900 1
save 300 10
save 60 10000

意思是:900s内,至少有一个key被更改则进行异步快照;300s内至少有10个key被更改;60s内至少有10000个key。

执行SAVE或者BGSAVE命令

SAVE命令,使redis同步进行快照,会阻塞来自客户端的请求。不推荐

BGSAVE命令,在后台异步进行快照,可以相应客户端请求。执行BGSAVE会立刻返回ok,表示开始执行快照操作,如果想要知道快照是否完成,通过LASTSAVE命令,获取最近一次成功执行快照的时间,返回unix时间戳。

快照过程

redis默认会将快照文件存储在redis工作目录的dump.rdb文件中。过程如下:

  1. redis使用fork函数复制一份当前进程的子进程;
  2. 父进程继续处理客户端发来的请求,子进程开始将内存中的数据写入硬盘中的临时文件
  3. 当子进程写入完所有的数据后会用该临时文件替换旧的rdb文件,本次快照完成。

注意: 当fork函数发生的一刻,父子进程共享同一内存数据,当父进程要更改其中某片数据时,操作系统会将该片数据复制一份,以保持子进程的数据不受影响,所以新的rdb文件存储的是fork一刻的内存数据。

rdb文件是经过压缩的二进制格式。

以上,可以看到这种方式的持久化明显存在缺陷。当redis异常退出,就会丢失最后一次快照以后的更改。如果数据相对重要,就要使用AOF方式了。

AOF方式

这种方式将所有的写命令追加到硬盘文件中,这个过程会降低redis的性能,但是大部分情况下这个影响是可以接受的,另外使用较快的硬盘可以提高AOF的性能。

默认情况redis是没有开启AOF的,可以通过appendonly参数启用:

appendonly yes

aof文件和rdb文件的位置相同,默认文件名是appendonly.aof,可以通过appendfilename参数修改:

appendfilename XXX.aof

AOF文件的重写

比如我们有两条写命令:

set foo 1
set foo 2
set foo 3

明显,前面两条都是没用的。这时候我们希望优化aof文件。

可以在配置文件redis.conf里面配置:

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

auto-aof-rewrite-percentage意思是当目前的aof文件大小超过上次重写时的aof文件大小的百分之多少时,会再次自动重写,如果之前没有重写过,则以启动时的aof文件大小为依据。

aotu-aof-rewrite-min-size限制了允许自动重写的最小aof文件大小,通常在aof文件太小的时候我们并不关心。

此外还可以手动重写:

BGREWRITEAOF

重写的过程只和内存中的数据有关,和旧的aof文件无关。