RDB快照(snapshot)

常用操作

在默认情况下,Redis会将快照数据放到 “dump.rdb” 的文件中。并且该文件是一个被压缩过的二进制文件。

而且可以对Redis设置多个生成RDB快照的策略。让Redis在某一个时间段内,修改次数达到设定的阈值,则触发持久化。

打开redis.conf 配置文件,配置几条规则,这里设置阈值较小,方便测试。

# 存储RDB文件的文件名
dbfilename dump.rdb

# 存储数据目录,RDB 、 AOF 等文件都会存储在这个目录下
dir /root/redis/data/6379/dir

# 设置30秒内 有20个更新操作即生成一个RDB快照
save 30 20

# 设置60秒内 有10个更新操作即生成一个RDB快照
save 60 10

尝试手动在30秒内执行20个更新操作,观察dir目录下确实生成了一个 “dump.rdb” 文件,不过因为这是二进制的压缩文件,所以查看时,会是乱码状态。 QQ20200610-210658@2x

除了这种方式以外,还有手动生成快照的命令,可以通过redis的客户端,发送命令到redis,让redis生成数据快照保存下来。

先把 dump.rdb 文件删除,接着我们直接使用 “src/redis-cli -p 6379 ” 进入redis客户端,执行save命令。

QQ20200610-211224@2x

这时候再次进入dir 目录下,可以看到新的dump.rdb 文件生成了。

可以尝试手动将redis的进程kill掉,然后重启,会发现数据被恢复回来了。

不过需要注意的是,save是一个同步命令,它会在生成快照的这个时间段,阻塞其他的命令。

bgsave,是redis提供的异步生成快照的命令(bg是background的简写),当redis的单线程解析到 “bg” 这个指令的时候,就会fork一个子进程去执行命令。

比如bgsave,就会fork出来一个子进程去生成RDB文件快照。

而且,通过配置文件的策略自动生成RDB快照,是以bgsave的命令生成的。不会阻塞客户端的其他命令。

如果要关闭RDB持久化方案,将redis.conf 配置文件中的所有save 配置注释掉即可。

缺点

RDB快照方案的持久化,存在较大的可能,数据丢失问题。

倘若设置的60秒以内1000个更新操作则生成RDB快照,如果在这60秒以内没有达到1000个更新操作的阈值,而Redis宕机了的话,则会丢失这60秒的数据。

AOF 持久化方案

常用操作

从Redis的1.1版本开始,增加了一种AOF持久化( append-only file ),它会将每一条更新命令以RESP协议的方式,追加在文件 “appendonly.aof” 中。

当Redis重启时,会从aof文件里读取命令,重新执行一遍,以此来恢复数据。

修改配置文件:

# 是否启用 AOF,  no、yes 
appendonly yes

# AOF保存的文件名,默认 appendonly.aof
appendfilename "appendonly.aof"

# 同步策略  每秒同步一次
appendfsync everysec

同步策略有三种

  • appendfsync always 每次有新的命令都会执行一次fsync,追加命令到文件,安全性高,性能低下。
  • appendfsync everysec 每秒会执行一次fsync,把新的命令追加到文件里。倘若故障,会丢失一秒的数据。(Redis默认配置)
  • appendfsync no 从不fsync到文件 ,将数据交给操作系统来处理。更快,也更不安全的选择。

测试一下执行多次incr命令后,是否会追加到aof文件里。

QQ20200610-221432@2x

查看aof文件, 可以看到有6个incr指令都被追加到了appendonly.aof的文件里。QQ20200610-221914@2x

这时候aof的弊端也显现出来了,就是aof的文件必然会非常的大,假设这个zhangsan字段,被incr了一万次,那么就会在aof文件里生成一万条incr指令,

AOF 重写

aof里面可能会存在大量没用的指令,造成文件过大,数据恢复较慢。

那么在这种场景下,aof定期重写,可以做到一定的优化,它会定期将当前最新的数据,生成aof文件。

通过修改redis.conf配置,让redis自动执行aof重写。

# aof 文件至少要达到64mb 以后才会执行aof重写
auto-aof-rewrite-min-size 64mb

# aof文件自上一次重写后文件大小增长了100%则再次触发重写
auto-aof-rewrite-percentage 100

可以通过 “bgrewriteaof” 指令,手动进行aof重写,而且该指令会fork一个新的子进程到后台去处理。

我们进入redis客户端,手动执行一次“bgrewriteaof”后,查看一下aof文件内容。可以明确的看到多条incr指令变成了一个set zhangsan 6 的指令。

QQ20200610-224605@2x

redis启动时如果既有rdb文件又有aof文件则优先选择aof文件恢复数据,因为aof一般来说数据更全一点。

混合持久化

Redis重启时,我们很少用RDB来恢复数据,因为RDB可能会丢失过多的数据,通常使用AOF来恢复数据,对命令重新执行。

但是重新执行AOF,效率对于RDB来说会低很多,有可能导致恢复数据时间过长。

Redis 为了解决这个问题,引入了混合持久化。

通过配置redis.conf 可以开启混合持久化。

aof-use-rdb-preamble yes

开启了混合持久化后,AOF在进行重写的时候,不再是简单的最新的数据存储在apf文件中。

而是将重写这一刻之前的内存做RDB快照处理,并且将RDB快照内容和增量的AOF修改命令存在一起,并一起存入到新的文件中。

新的文件一开始不叫“appendonly.aof”,等到重写完新的AOF文件才会进行改名,原子的覆盖原有的AOF文件,完成新旧两个AOF文件的替换。

在混合持久化开启下,Redis重启会先加载“appendonly.aof” 文件中的RDB数据,其次再加载“appendonly.aof” RDB后面的 AOF增量命令。

接下来测试拥有RDB和AOF增量数据的 “appendonly.aof” 文件会是什么样的。

在打开持久化后,手动执行一次AOF重写,也就是“bgrewriteaof”命令,当我们再次查看aof文件的时候,应该是下面这样的乱码,这些是RDB格式的二进制数据,因为在生成RDB之后,重写AOF之前,没有新的修改命令,所以这里看不到AOF的命令。

REDIS0009�      redis-ver6.0.5�
�edis-bits�@�ctime�T��^used-mem�3
 aof-preamble��zhangsan����dD�C�A

打开redis客户端,再次执行几次incr命令之后,再次查看aof文件,如下。可以看到,上面的是RDB数据,下面的是AOF增量数据。

QQ20200610-230841@2x