13518219792

建站动态

根据您的个性需求进行定制 先人一步 抢占小程序红利时代

Redis持久化:RDB和AOF

Redis 数据存储在内存中,如果不想办法将数据保存到硬盘上,一旦Redis重启(退出/故障),内存的数据将会全部丢失。我们肯定不想 Redis 里的数据由于某些故障全部丢失(导致所有请求都走 MySQL),即便发生了故障也希望可以将Redis原有的数据恢复过来,这就是持久化的作用。

专注于为中小企业提供成都网站设计、网站制作服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业博望免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了超过千家企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。

Redis 提供了两种不同的持久化方法来将数据存储到硬盘里边:

RDB内存快照,让宕机快速恢复

1.什么是RDB内存快照?

在 Redis 执行“写”指令的过程中,内存数据一直会变化,所谓内存快照,指的就是 Redis 内存中数据在某一时刻的状态数据,好比时间定格在某一时刻。当我们拍照时,通过照片就能把某一时刻的瞬间画面完全记录下来。Redis 跟这个类似,就是把某一刻的数据以文件的形式拍下来,写到磁盘上,这个快照文件叫做 RDB 文件,RDB 就是 Redis Database 的缩写。

2.生成RDB的策略

Redis 并不会在每次执行“写”指令的时候都触发 RDB 写磁盘,只需要在执行内存快照的时候写磁盘,这样既保证了唯快不破,还实现了持久化,宕机快速恢复。

我们知道 Redis 的单线程模型决定了我们要尽可能地避免会阻塞主线程的操作,所以就需要尽可能地避免 RDB 文件生成阻塞主线程。为此Redis提供了两个指令用于生成 RDB 文件:

除了手动调用 SAVE 或者 BGSAVE 命令生成 RDB 文件之外,我们可以使用配置的方式来定期执行:在默认的配置下,如果以下的条件被触发,就会执行 BGSAVE 命令。

save 900 1              #在900秒(15分钟)之后,至少有1个key发生变化,
save 300 10             #在300秒(5分钟)之后,至少有10个key发生变化
save 60 10000           #在60秒(1分钟)之后,至少有10000个key发生变化

3.RDB实现原理

在RDB执行期间为了保证快照的数据一致性,只能处理读操作,不能修改正在执行快照的数据,这种场景,Redis 是允许的。那 Redis 是如何实现一边处理写请求,同时生成RDB文件的呢?

Redis 使用操作系统的多进程写时复制技术 COW(Copy On Write)来实现快照的持久化。

Redis 在持久化是会调用 glibc 的函数(linux系统中最底层的api)fork产生一个子进程,快照持久化完全交给子进程来处理,父进程继续处理客户端请求。子进程刚刚产生时,它和父进程共享内存里面的代码段和数据段,这时可以将父子进程想象成一个连体婴儿,共享身体。这是Linux操作系统的机制,为了节约内存资源,所以尽可能让它们共享起来,在进程分离的一瞬间,内存的增长几乎没有明显的变化。

BGSAVE 子进程可以共享主线程的所有内存数据,读取主线程的数据并写入到 RDB 文件。当主线程执行写指令修改数据的时候,这个数据就会复制一份副本,BGSAVE 子进程读取这个副本数据写到 RDB 文件。

在执行 SAVE 或 BGSAVE 命令创建一个新的 RDB 文件时,程序会对数据库中的键进行检查,已过期的键不会被保存到新创建的RDB 文件中。这既保证了快照的完整性,也允许主线程同时对数据进行修改,避免了对正常业务的影响。

4.RDB的优缺点

优点

缺点

另外,过于频繁的执行全量数据快照,有两个严重的性能开销:

AOF写后日志,避免宕机数据丢失

1.什么是AOF写后日志?

AOF(Append Only File)写后日志,AOF 持久化就是将修改数据库状态的命令保存到 AOF 文件中,被写入的命令都是以 Redis 的命令请求协议格式保存的,Redis 的命令请求协议是纯文本格式。

假设 AOF 日志记录了 Redis 实例创建以来所有的修改指令序列,那么就可以通过一个空的 Redis 实例顺序执行所有的指令,也就是“重放”,来恢复Redis当前实例的内存数据结构的状态。

写后日志和写前日志的对比

写前日志(WAL,Write Ahead Log):在实际写数据之前,将修改的数据写到日志文件中,故障恢复得以保证。比如 MySQL Innodb 存储引擎中的 redo log(重做日志)便是记录修改的数据日志,在实际修改数据前先记录修改日志再执行修改数据。

写后日志:先执行“写”指令请求,将数据写入内存,再记录日志。

日志格式

当 Redis 接收到 “set key value” 命令将数据写入到内存之后,会按照如下格式写入 AOF 文件:

写后日志的好处

写后日志避免了额外的检查开销,不需要对执行的命令进行语法检查。如果使用写前日志的话,就需要先检查语法是否有误,否则日志记录了错误的命令,在使用日志恢复的时候就会报错。另外,写后记录日志,避免了阻塞当前“写”指令的执行。

2.写回策略

使用 AOF 也不是万无一失的,假如 Redis 刚执行完指令,还没记录日志就宕机了,就有可能丢失这个命令的相关数据;还有, AOF 避免了当前命令的阻塞,但是可能会给下一个命令带来阻塞的风险。AOF 日志是主线程执行的,将日志写入磁盘过程中,如果磁盘压力过大就会导致磁盘写操作很慢,导致后续的“写”指令阻塞。

发现了没,这两个问题与磁盘写回有关,如果能合理控制“写”指令执行完后 AOF 日志写回磁盘的时机,问题就可以迎刃而解。

为了提高文件的写入效率,当用户调用 write 函数,将一些数据写入到文件时候,操作系统通常会将写入数据暂时保存在一个内存缓冲区里,等到缓冲区的空间被填满或者超过了制定的限制之后,才真正将缓冲区中的数据写入到磁盘里面。

这种做法虽然提高了效率,但也为写入数据带来了安全问题,因为如果计算机发生停机,那么保存在内存缓冲区里的写入数据将会丢失。为此系统提供了 fsync 和 fdatasync 两个同步函数,它们可以强制让操作系统立即将缓冲区中的数据写入到硬盘里,从而确保写入数据的安全性。

与之相对应 Redis 提供了 AOF 配置项 appendfsync 写回策略来控制 AOF 持久化功能的效率和安全性。

appendfsync always     # 同步写回,写指令执行完毕立即将 aof_buf 缓冲区中的内容写到 AOF 文件。
appendfsync everysec   # 每秒写回,写指令执行完毕,把日志写到 aof_buf 缓冲区,每隔一秒同步到磁盘,该策略为AOF的默认策略。
appendfsync no         # 操作系统控制,写指令执行完毕,把日志写到 aof_buf 缓冲区,由操作系统决定何时写回磁盘。

3.AOF重写机制

由于 AOF 记录的是一个个指令的内容,这就会导致保存的文件太大,另外,故障恢复的时候需要执行每一个指令,如果日志文件太大,整个恢复过程就会非常慢。为此,Reids 设计了 AOF 重写机制,提供了 bgrewriteaof 命令用于对 AOF 文件进行瘦身。

其原理就是开辟一个子进程对内存进行遍历转换成一系列 Redis 的操作指令,序列化到一个新的 AOF 日志文件中,序列化完毕后再将操作期间发生的增量 AOF 日志追加到这个新的 AOF 日志文件中,追加完毕后立即替换旧的 AOF 日志文件。瘦身工作就完成了。

重写机制有“多变一”的功能,将旧日志中的多条指令,在重写后就变成了一条指令。如下所示:三条 lpush 命令,经过 AOF 重写后生成一条,对于多次修改的场景,缩减效果明显。

重写过程

和 AOF 日志由主线程写回不同,重写过程实际是由后台子进程 bgrewriteof 完成的,这也是为了避免阻塞主线程,导致性能下降。

总的来说,一共出现两个日志,一次内存数据拷贝,分别是旧的 AOF 日志和新的 AOF 重写日志和Redis 数据拷贝。大致流程如下图所示:

在上图中,Redis 会将重写过程中接收到的“写”指令操作同时记录到旧的 AOF 缓冲区和新的 AOF 重写缓冲区,这样重写日志也保存了最新的操作,等到拷贝数据的所有操作记录重写完成后,重写缓冲区记录的最新操作也会写到新的 AOF 文件中。

每次 AOF 重写时,Redis 会先执行一次内存拷贝,用于遍历数据生成重写记录。防止 AOF 重写过程失败,导致原 AOF 文件被污染,无法做恢复使用。

使用两个日志可以保证在重写过程中,新写入的数据不会丢失,并且保持数据的一致性。

4.AOF 的优点和缺点

优点

缺点

混合日志模型

重启 Redis 时,我们很少使用 RDB 来恢复内存状态,因为可能丢失大量数据。通常采用 AOF 日志重放,但是重放 AOF 日志性能相对 RDB 来说要慢很多,在Redis实例很大的情况下,启动需要花费很长时间。

Redis 4.0 为了解决这个问题,提供了一个新的持久化选项--混合持久化,将 RDB 文件的内容和增量 AOF 日志文件存放到一起,这里的 AOF 日志不再是全量的日志,而是自持久化开始到持久化结束的这段时间发生的增量 AOF 日志,通常这部分日志很小。

在 Redis 重启的时候,先加载 RDB 的内容,然后再重放增量 AOF 日志,这样的操作既保证了 Redis 重启速度,又降低数据丢失风险。

总结

参考

Redis设计与实(https://weread.qq.com/web/reader/d35323e0597db0d35bd957bk73532580243735b90b45ac8)

Redis核心技术与实战(https://time.geekbang.org/column/intro/329)


当前文章:Redis持久化:RDB和AOF
网页链接:http://cdbrznjsb.com/article/dhgsjdj.html

其他资讯

让你的专属顾问为你服务