详细介绍Redis持久化机制RDB和AOF

Redis/缓存系统
238
0
0
2024-01-13
标签   Redis

今天分享一下Redis的数据持久化方式,我们知道,Reids是一个高性能的缓存中间件,它的高性能是因为它是基于内存的,我们知道直接操纵内存是比较快的,不过一些美好的事物总会有牺牲一些功能,因为是基于内存,所以当机器发生宕机,那么数据就会完全丢失,Redis怎么可能不会去重视这个问题呢,所以它也提供了数据持久化的方式。

持久化方式

Redis提供了两种数据持久化的方式,分别为RDB和AOF,RDB是基于内存快照的,它会将某一时刻Redis的内存状态写入磁盘,RDB也是Redis默认采用的持久化方式,AOF则是基于文件追加的机制来进行持久化的,如果我们开启AOF持久化,那么每写入一条数据,这个写入数据的命令就会被追加到AOF文件的尾部,下面详细介绍这两种持久化方式。

RDB持久化

RDB是Redis默认的持久化方式,它是基于内存快照的持久化方式,何为快照?快照就是某一时刻Redis内存中的所有数据,就好比我们使用WPS编写文档,突然有事情需要处理,这时候我们要将电脑关闭,为了不让编辑的内容丢失,我们关闭WPS时它会提醒保存文档,这时候就会把到我们最后一刻操作之前的所有数据都保存下来,下次打开的时候 ,我们可以从上次编辑的地方继续。

RDB配置

我们关注以下三个配置就行

save 3600 1 300 100 10 10000

dbfilename dump.rdb

dir ./
save

配置达到什么条件才保存内存快照,这个配置表示如果在3600秒内进行一次写操作,或者在300秒内进行100次写操作,又在10秒内进行10000次写操作,那么就会保存内存快照。

dbfilename

表示生成的RDB二进制文件名,默认为dump.dbdir ./是生成的RDB二进制文件的存放路劲。

当上面的save中的条件触发,那么Redis就会保存内存快照,当然,我们也可以直接使用SAVEBGSAVE命令来保存内存快照,save这里的配置到最后还是去执行SAVEBGSAVE命令,下面介绍SAVEBGSAVE命令。

SAVE和BGSAVE命令

在Redis命令行执行SAVE命令或者BGSAVE命令都可能保存快照,只不过SAVE命令会阻塞Redis服务器,这时候客户端发送的所有请求Redis都会拒绝,如果RDB文件比较小的还好,如果比较大,那么恢复数据就需要花费一定的时间,对于客户端来就很不友好,所以这时候我们可以使用BGSAVE命令,执行BGSAVE命令,Redis会fork一个子进程去保存内存快照,这样Redis服务器就不会阻塞。

下面我们对配置进行修改来测试rdb。

改成下面配置,那么10s内如果有1次写操作,就会保存当前快照。

save 3600 1 300 100 10 1

我们往Redis中添加一个key后,后台就会打印保存到磁盘的日志。

在Redis源码中,保存RDB文件在rdb.c文件中,使用rdbSaveBackgroup函数保存RDB文件,里面会fork一个子进程,然后调用rdbSave保存rdb文件。

恢复RDB文件

如果Redis服务发生宕机,那么在服务器恢复后,Redis会加载rdb文件进行恢复,Redis没有专门恢复rdb文件的命令,服务器在启动后会直接判断是否存在rdb文件,如果存在则进行恢复。

在redis中,在rdb.c文件中使用rdbLoad函数进行加载rdb文件和恢复到Redis内存中。

AOF持久化

AOF (Append Only File)持久化机制会记录每一条写入 Redis 数据库的命令,将其追加到文件末尾中,以此来保证数据的持久化和安全性。AOF 持久化方式保证了Redis的每一次写的操作都可以被记录到文件中,增加了数据的可靠性和稳定性。这种方式下,每个写入命令都将同步到 AOF 文件中。AOF 优先于 RBD 进行持久化,如果 Redis 服务重启之前启用了 AOF 持久化方式,那么 Redis 会自动从 AOF 日志文件中重建数据。AOF 产生的日志文件是一个文本文件,易于查看,但也可能稍微耗时一些。

AOF配置

我们来关注AOF的几个配置

appendonly yes

appendfilename "appendonly.aof"

appenddirname "appendonlydir"

appendfsync everysec
appendonly

表示是否开启AOF持久化机制,默认为no,表示不开启,Redis默认不开启AOF持久化,所以如果我们需要开启AOF持久化,那么就需要将其设置为yes。

appendfilename

表示aof文件的名称,开启aof持久化,每个写操作的命令会被写入aof文件中,redis7以后,不单单生成了appendonly.aof文件,而是生成了三个文件,

appenddirname

表示aof所在文件夹的名称,默认为appendonlydir。

appendfsync

表示设置同步aof文件的时机,当我们设置了aof持久化机制,写入的命令并不会直接写入磁盘中的aof文件,而是保存在内存的一个缓冲区aof_buf中,然后再通过相应的机制刷盘到磁盘中,提供了 always,everysec,no 三种选项

  • always:每当向缓冲区文件中添加数据时,立即执行同步操作将缓冲区的内容同步到aof文件中。这样可以保证数据的完整性,但会导致 Redis 性能下降。
  • everysec:每秒将aof缓冲区中的数据同步到磁盘。这种方式既保证了数据的完整性,又可以大大提高 Redis 的性能。
  • no:不执行同步操作,而是交由操作系统控制同步时机。这种方案性能最好,但也有可能会导致数据丢失。

测试AOF持久化机制

开启了AOF持久化机制后,我们往Redis中写入几条数据,然后查看aof文件。

往Redis中写入了一个名为 steakliu 的key,value为空,然后为steakliu这个key设置value为 steakliu is a handsome boy,这是两个命令,我们查看aof文件,发现里面有这两条命令,里面还有一个 SELECT 0 ,它是Redis自动加入的。

在Redis中有一个时间循环机制,它会接受来自客户端的请求,然后进行处理,当然也包括将命令写入aof文件中,最终会调用flushAppendOnlyFile函数。

上面代码中我们看到里面有一个aof_buf,它的类型是sds,在Redis中sds名为简单动态字符串(Simple Dynamic String)。

sds aof_buf;   /* AOF buffer, written before entering the event loop */

上面的配置中我们说了appendfsync,它的作用就是将aof_buf缓冲区中的数据同步到aof文件中。

通过AOF恢复数据

将Redis进程kill掉,然后重新启动Redis,我们看出它会去加载aof文件进行数据恢复。

因为aof文件中保存的是写操作的命令,所以在进行恢复的时候就是重新执行一下这些命令就能进行恢复。

AOF重写

随着aof文件的变大,如果我们的Redis服务出现故障后重启,它使用aof来恢复数据时,就会比较耗时,如果里面存在大量重复的命令,比如下面我们对steak-key进行反复的修改,但是实际上我们只需要最新的value,而里面出现了大量的重复,就会导致恢复时间比较慢。

为了解决这个问题,Redis提供了aof重写机制,它使用了BGREWEITEAOF命令来对aof文件进行重写,Redis会开启一个子进程来进行重写,它会编辑aof文件中命令,去除重复的,然后转换到一个新的aof文件中。

循环添加重复的key

如下,我们往redis中循环添加两个重复的key,分别是steak-keysteak-pai

我们观察一下aof文件夹中的几个aof文件如下。

稍等一会儿,我们再看aof文件夹下面的这几个aof文件如下:

从上面我们可以看出,appendonly.aof.1.base.aof变为了appendonly.aof.2.base.aofappendonly.aof.1.incr.aof变为了appendonly.aof.2.incr.aof,由此可见aof文件发生了重写。

我们查看appendonly.aof.2.base.aof的内容如下:

我们发现这个文件夹中只有两个key,也就是steak-keysteak-pai,如果不进行重写,那么就会存在大量重复的key,在进行恢复的时候就比较慢。

注:上面我们并没有开启RDB和AOF混合使用,所以我们能看到明文,如果开启了RDB和AOF混合使用,文件中则有RDB二进制数据和AOF内容,我使用的是Redis7版本,默认是开启RDB和AOF混合使用,可以在redis.conf中进行配置。

aof-use-rdb-preamble yes

yes表示开启RDB和AOF混合使用,no表示关闭,Redis7默认的是开启。

redis.conf配置

redis中有两个aof重写的配置。

auto-aof-rewrite-percentage 100

auto-aof-rewrite-min-size 64mb
  • auto-aof-rewrite-percentage 表示当 AOF 文件大小增长到上一次重写文件时的大小的百分之多少时,Redis 就会自动触发 AOF 重写。例如,当此配置项为 100 时,表示当 AOF 文件大小增长到上次重写时大小的两倍时,就会自动触发 AOF 重写。
  • auto-aof-rewrite-min-size 表示 Redis 在自动触发 AOF 重写时设置的 AOF 文件最小大小限制。例如,当此配置项为 64MB 时,如果 AOF 文件大小增长到达了触发自动重写的条件,但当前 AOF 文件大小还不到 64MB,则不会自动触发 AOF 重写。
从上面我们可以看出,aof如果不进行重写,那么如果出现大量的重复key,aof文件中就会保存了大量重复的命令,在进行aof恢复的时候,会做很多无用功

AOF和RDB优缺点比较

RDB的优点

RDB是一种快速而有效的备份方式,可以在特定的时间间隔内保存Redis数据的快照,储存快照文件的方式是写入硬盘中的二进制文件,所以很适合用来备份关键数据,RDB备份是二进制格式,所以比较小,使用起来比较节省存储空间。RDB还支持压缩备份,可以在备份数据时压缩文件大小,节省备份成本。

RDB的缺点

RDB在执行快照的时候,如果数据量较大,会造成Redis阻塞,如果服务器宕机,比如发生异常关机,那么这部分数据就可能发生丢失,因为RDB是定期进行备份,如果Redis服务器发生故障,那么会丢失上次备份到现在的数据。

AOF的优点

AOF是一种以日志的形式来记录Redis服务器所执行的所有写入操作,具有很好的复原能力,因此更适合于重要数据的保存,AOF支持在重写,以保证AOF文件不会无限增大导致读取缓慢。

AOF的缺点 AOF文件通常比RDB文件大,如果日志分析不当,则可能增加服务器I/O的负载,AOF方式的数据恢复速度通常比RDB方式的恢复速度慢,因为它还需要去一个一个地执行命令进行恢复。

AOF和RDB混合使用

AOF和RDB可以混合使用,上面我们也提到了RDB和AOF混合使用可通过aof-use-rdb-preamble配置,Redis7默认是开启混合持久化的,那么就会将RDB二进制内容和AOF增量内容保存在一起。

参考文档和书籍

Redis设计与实现[https://weread.qq.com/web/bookDetail/d35323e0597db0d35bd957b]

Redis官方文档[https://redis.io/docs/management/persistence/]