redis之AOF和RDB持久化

写在前面

在这里插入图片描述
redis数据存储在内存,为了避免服务器重启或者是宕机导致数据全部丢失,提供了数据持久化机制,有AOF(Append Only File)和RDB,接下来我们分别看下。

1:AOF

如下是我本地环境生成aof文件:
在这里插入图片描述

1.1:AOF日志的实现

首先我们需要配置appendonly yes来打开AOF持久化,之后当我们执行完数据修改命令后,redis就会将命令记录到aof文件中,这个过程不同于MySQL的WAL 机制(MySQL要解决主要问题数据的安全存储,而redis要解决的主要问题是高性能的数据存取),在写数据之前先写日志,redis是写数据之后再写日志,这样做的其中一个原因是可以不用对命令本身的语法进行校验了(既然都执行成功了,肯定语法没有问题),该过程如下图:

在这里插入图片描述

如执行命令set aa bbbb则生成的aof日志如下:

*3
$3
set
$2
aa
$4
bbbb

含义如下:

*3:命令由3部分组成
$数字:代表接下来是命令的一部分,数字代表该部分的长度

通过以上信息可以反推出命令set aa bbbb,就可以用来备份和恢复数据了。另外针对aof的写回策略提供了若干个参数来控制,接下来继续看下。

1.2:写回策略

目前redis的写回策略有三种,通过配置项appendfsync设置,如下:

Always:同步写回,使用主线程,所以会影响到主线程的性能。
Everysec:每秒写回,先将命令写到aof的缓冲区,然后其他线程每隔一秒写到aof文件。
No:操作系统控制写回,命令仅仅写道aof缓冲区,由操作系统控制写到aof文件。

对比如下表:
在这里插入图片描述

随着越来越多的命令写入到aof文件,aof文件会变得越来越大,而aof文件的不断增大可能会产生如下的问题:

1:达到了操作系统对单文件大小的限制,从而无法继续写入
2:文件增大之后数据写入的速度会变慢,影响写入性能
3:文件过大,数据恢复的速度慢

为了解决以上可能的问题,redis提供了AOF重写机制

1.3:AOF重写机制

aof重写动态图

aof重写机制的原理是多合一,即将多个命令合并成一个命令,因为可能会对一个key重复操作多次,所以同一个key的操作命令会被记录多次,但是对于恢复数据而言,只需要最终的一个数据状态就行了,所以根据数据当前的状态反向生成一条命令即可,这就是多合一的过程,如下图对一个list的多次操作执行重写的过程:

在这里插入图片描述
为了完成AOF重写过程,redis会fork处一个新的子进程bgrewriteaof,并将当前内存中的数据拷贝一份,然后使用当前最新的数据生成对应的命令,并写到一个新的aof文件中,这个过程就是AOF重写,可以参考下图:
在这里插入图片描述

aof重写完成后,就可以使用新的aof文件替换旧的aof文件了。

2:RDB

如下是我本地生成rdb文件:
在这里插入图片描述
前面我们分析了AOF持久化,但这种方式有一个问题,就是当修改命令变多时会导致文件过大,从而导致数据恢复速度慢。这个问题我们可以通过RDB(redis database)来解决。

2.1:原理和配置

  • 原理
    Redis通过定时任务扫描数据的变化是否满足某个规则,如果是满足了规则则使用操作系统提供的相关机制,则调用fork()创建子进程,对redis当前的内存空间生成dump.rdb快照文件,该文件存储了内存数据对应的二进制数据,可以直接加载到内存中来恢复redis的数据,恢复速度快。
  • 配置策略
    redis有两种配置策略,一种是手动触发策略,另外一种是自动触发策略,其中自动触发策略可以通过save,bgsave命令来手动触发,前者会使用主线程执行备份,如下:
127.0.0.1:6379> SAVE
OK
127.0.0.1:6379> BGSAVE
Background saving started
127.0.0.1:6379>  LASTSAVE
(integer) 1611298430

注意:LASTSAVE 命令用于查看 BGSAVE 命令是否执行成功。

自动触发策略通过如下配置:

save 900 1
save 300 10
save 60 10000

以上配置的格式是save 时长 修改次数,以上配置的含义是如果是在900内发生至少一次更新,或者在300内发生至少10次更新,或者是60秒内发生至少10000次更新,则执行bgsave生成rdb快照文件,并且生成文件后用于触发策略的计数和计时都会重置。

2.2:复制都有哪些问题

在进行复制的时候,还允许数据更新吗?如果是允许更新的话,就会有数据一致性的问题,如果是不允许更新的话,则会影响正常的数据更新。当然,影响正常的数据更新肯定是不允许的,因为会严重影响业务,甚至可能会出现线上事故,而数据一致性的问题更加不允许了,如果是后续使用其恢复数据的话,问题就更大了,所以只需要解决允许更新时有数据一致性的问题就可以了,redis的做法是使用COW(将要更新的数据copy出一份,直接更新copy的那份)机制,即更新时将更新目标对应的内存页复制出来一份,对复制的内存页执行更新,则原始数据不会受到影响,待rdb生成完毕后,再将COW的内存页重新写回到原始内存页就行了(这个过程很快),这样就能解决数据一致性的问题了,参考下图:

在这里插入图片描述
好了,现在我们已经能够在不影响客户端更新的情况下获取符合数据一致性要求的快照了,但是更新时时刻都在发生的,那么在这次快照生成之后多久之后再次生成呢,如果是频率过慢,比如十分钟一次,如果发生宕机,则上次快照到宕机时刻的所有数据都会丢失,如果是过快,比如一秒一次,这样可以大大减少宕机造成的数据丢失,但是会对系统的IO等资源造成比较大的压力,而且创建子进程的fork操作也是会阻塞主线程,因此也会影响到正常的数据操作,其实我们只需要处理好两次快照之间的数据就行了,一种方案是记录修改日志,即记录对数据都做了什么修改,如下图:

在这里插入图片描述

这种方案也没有太大问题,但是在redis4.0中提供了更好的一种方案,即通过rdb和aof混用的方式,就巧妙的将这个问题解决了,即两次快照空隙的数据修改通过aof日志方式记录,则就既能使用到rdb恢复速度快的优势,也能够规避aof文件过大带来的问题,发挥其记录简单的优势,此时,rdb就是全量备份,而aof就是增量备份,二者混用执行可能如下图:
在这里插入图片描述
真是一种完美的解决方案,可以在线上起来。

写在后面

参考文章列表:

Redis RDB持久化详解(原理+配置策略)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值