— redis — 1 min read
在redis中提供了两种持久化方式RDB(快照)和AOF,不过两种各有利弊,接下来详细说一下。
RBD持久化是redis的默认策略。
redis会生成一个二进制文件,默认情况下dump.rdb会叫这个名字,但这个文件是可以被redis还原成文件生成时redis的状态。
redis支持两个命令生成RDB文件,SAVE
和BGSAVE
,主要区别在一前者为阻塞方式生成文件。
后者则是以子进程(fork)的方式进行生成文件,也就以为这不会产生阻塞,父进程可以继续响应请求,这里主要介绍BGSAVE
该种方式,应为第一种方式将会阻塞,在大量数据的情况下,服务将尝试建不可用。
Linux 提供的一种进程机制,当前进程调用 fork 将会产生一个子进程,该子进程会与当前进程共享一块内存,也就是数据段和代码段都是相同的。
子进程在在得到了内存后,开始疯狂的写入文件做持久化,此时若当前进程接受到新的请求,进行数据更改时,将会把共享的内存段复制一份,当前进程会基于新的内存数据进行操作。 这样一来,我们就不用再去担心当前进程对即将产生的快照产生影响了。
若在BGSAVE执行期间,手动再次调用SAVE
、BGSAVE
或BGREWRITEAOF
命令会产生两次备份么?
redis规定在备份命令执行期间,再次执行以上命令则不会被执行,为了防止产生竞争同时执行两个rdbSave
,SAVE
、BGSAVE
两个命令不会执行。
而BGREWRITEAOF
命令会在,前一个命令执行完成后开始执行。
但如果是BGREWRITEAOF
命令正在执行,此时客户端发送BGSAVE
命令则会被拒绝。
具体原因是两个命令都是由子进程执行的,所以在操作方面没有冲突的地方,不能同时执行的原因是性能上的考虑——并发出两个子进程,并且这两个子进程都会同时执行大量 io(磁盘写入)操作。
AOF 持久化在 Redis 中默认为关闭,他类似于 Mysql 的 Binlog,是一个用来记录 Redis 所有操作命令的日志,若在 redis 启动时就开启了AOF,那么他将记录所有的操作命令,在进行恢复时只需要进行 AOF 的命令重放即可。
正因为他记录了所有的操作命令,所以他也存在一些问题:
redis 中 AOF 的写操作是在逻辑处理之后,导致 redis 无法进行数据的回滚,这也是与 MySQL 的 binlog不同的一点。
bgrewriteaof:针对上述的问题,Redis 在 2.4 之后也使用了 bgrewriteaof 对 AOF 日志进行瘦身。
bgrewriteaof 命令用于异步执行一个 AOF 文件重写操作。重写会创建一个当前 AOF 文件的体积优化版本。
由于两种方式都存在一些问题,使用 RDB 会导致在写入时丢失新写入的数据,而使用 AOF 会存在持久化文件过大导致恢复时停机时间较长的问题。
所以在Redis4.0之后引入了新的持久化机制,将 RDB 与 AOF 进行结合,使用 RDB 策略进行持久化,同时将这段时间内的操作使用 AOF 进行记录,这样既能够快速的生成文件,同时 AOF 不在需要进行全量的操作记录,只需要保存前一次 RDB 开始后的增量 AOF 即可,这样生成的 AOF 持久化文件将不会再过大。