Redis持久化之AOF

1、AOF持久化介绍

Redis 持久化的另一种方式AOF,全称是append only file,AOF以独立日志的方式记录每次写命令(读操作不记录),重启时再重新执行AOF文件中的命令来恢复数据。AOF会先把命令追加在AOF缓冲区,然后根据对应策略写入硬盘(appendfsync),它只许追加文件但不可以改写文件。换言之,Redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。

注意:如果RDB和AOF两种方式都打开的话,Redis会优先使用AOF的方式。

2、自动触发

和RDB一样,配置在redis.conf文件里,在 redis.conf 配置文件的 APPEND ONLY MODE 部分下:

补充:当然你也可以通过在Redis的客户端调用CONFIG SET命令设置(例如:CONFIG SET appendonly yes)。

image

APPEND ONLY MODE 中可配置的属性有如下:

①、appendonly:默认是关闭的,也就是说redis 默认使用的是rdb方式持久化,如果想要开启 AOF 持久化方式,需要将 appendonly 修改为 yes。

②、appendfilename :aof文件名,默认是"appendonly.aof"

③、appendfsync:aof持久化策略的配置(同步频率),有3种;

  • always:表示每次写入都执行fsync,以保证数据同步到磁盘,效率很低,不建议配置;
  • everysec:表示每秒执行一次fsync,如果一秒内出现宕机,可能会导致丢失这1s数据。通常选择 everysec ,兼顾安全性和效率。
  • no:表示不执行fsync,由操作系统保证数据同步到磁盘,速度最快,但是不太安全;

image

④、no-appendfsync-on-rewrite:在aof重写或者写入rdb文件的时候,会执行大量IO,此时对于everysec和always的aof模式来说,执行fsync会造成阻塞过长时间,no-appendfsync-on-rewrite字段设置为默认设置为no。如果对延迟要求很高的应用,这个字段可以设置为yes,否则还是设置为no,这样对持久化特性来说这是更安全的选择。   设置为yes表示rewrite期间对新写操作不fsync,暂时存在内存中,等rewrite完成后再写入,默认为no,建议yes。Linux的默认fsync策略是30秒。可能丢失30秒数据。默认值为no。

⑤、auto-aof-rewrite-percentage:默认值为100。aof自动重写配置,当目前aof文件大小超过上一次重写的aof文件大小的百分之多少进行重写,即当aof文件增长到一定大小的时候,Redis能够调用bgrewriteaof对日志文件进行重写。当前AOF文件大小是上次日志重写得到AOF文件大小的二倍(设置为100)时,自动启动新的日志重写过程。

⑥、auto-aof-rewrite-min-size:64mb。设置允许重写的最小aof文件大小,避免了达到约定百分比但尺寸仍然很小的情况还要重写。

⑦、aof-load-truncated:aof文件可能在尾部是不完整的,当redis启动的时候,aof文件的数据被载入内存。重启可能发生在redis所在的主机操作系统宕机后,尤其在ext4文件系统没有加上data=ordered选项,出现这种现象  redis宕机或者异常终止不会造成尾部不完整现象,可以选择让redis退出,或者导入尽可能多的数据。如果选择的是yes,当截断的aof文件被导入的时候,会自动发布一个log给客户端然后load。如果是no,用户必须手动redis-check-aof修复AOF文件才可以。默认值为 yes。

3、手动触发

使用bgrewriteaof命令:Redis主进程fork子进程来执行AOF重写,这个子进程创建新的AOF文件来存储重写结果,防止影响旧文件。因为fork采用了写时复制机制,子进程不能访问在其被创建出来之后产生的新数据Redis使用“AOF重写缓冲区”保存这部分新数据,最后父进程将AOF重写缓冲区的数据写入新的AOF文件中然后使用新AOF文件替换老文件。

4、为什么要重写以及AOF重写原理

①、为什么重写

由于AOF持久化是Redis不断将写命令记录到 AOF 文件中,AOF 的文件会越来越大,占用服务器内存越大以及 AOF 恢复要求时间越长。为了解决这个问题,Redis新增了重写机制,当AOF文件的大小超过所设定的阈值时,Redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集。可以向 Redis 发送 BGREWRITEAOF 命令,这个命令会移除 AOF 文件中冗余的命令来重写 AOF 文件,使 AOF 文件的体积变得尽可能地小。实际上 AOF 文件重写并不需要对现有的 AOF 文件进行任何读取、分析或者写入操作,这个功能是根据通过读取服务器当前数据库状态实现的。

②、重写(rewrite)原理

来自:彻底搞懂Redis持久化之AOF原理

image

  • aof_rewrite_buf:rewrite(重写)缓冲区、aof_buf:写命令存放的缓冲区
  • 开始bgrewriteaof的时候,判断当前有没有bgsave/bgrewriteaof在执行,若有,则不执行,这个再rdb篇幅也有提到,以及下面很多fork()知识在rdb都有提到。彻底搞懂Redis持久化之RDB原理
  • 主进程fork()出子进程,在执行fork()这个方法的时候是阻塞的,子进程创建完毕后就不阻塞了
  • 主进程fork完子进程后,主进程能继续接收客户端的请求,所有写命令依然是写入AOF文件缓冲区并根据配置文件的策略同步到磁盘的。
  • 因为fork的子进程仅仅共享主进程fork()时的内存,后期主进程在更改内存数据,子进程是不可见的。因此Redis采取重写缓冲区(aof_rewite_buf)保存fork之后的客户端请求。防止新AOF文件生成期间丢失主进程执行的新命令所生成的数据。所以此时客户端的写请求不仅仅写入原来的aof_buf缓冲区,还写入了重写缓冲区。这就是我为什么用深蓝色的框给他两框到一起的原因。
  • 子进程通过内存快照的形式,开始生成新的aof文件。
  • 新aof文件生成完后,子进程向主进程发信号。
  • 主进程收到信号后,会把重写缓冲区(aof_rewite_buf)中的数据写入到新的AOF文件(主要是避免这部分数据丢失)
  • 使用新的AOF文件覆盖旧的AOF文件,且标记AOF重写完成。

AOF重写--对比下面两组命令:

 两组命令执行后对于count来说最终的值是一致的,但是进行AOF重写后省略了中间过程,可以让AOF文件体积更小。

AOF 文件重写触发机制:

①、手动重写:

  • bgrewriteaof

②、自动重写:在redis.conf 配置文件中修改

  • auto-aof-rewrite-min-size size  #默认值为100
  • auto-aof-rewrite-percentage percentage  #默认64mb

也就是说默认Redis会记录上次重写时的AOF大小,默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发。实际工作中不要进行频繁的AOF重写,因为CPU资源和硬盘资源二者之间肯定是CPU资源更加宝贵,所以不应该过多耗费CPU性能去节省硬盘空间。

5、AOF工作原理

当 Redis 需要以 AOF的形式持久化文件时, 服务器执行以下操作:

image

  1. 所有的写入命令追加到aof缓冲区
  2. AOF缓冲区根据对应appendfsync配置向硬盘做同步操作
  3. 定期对AOF文件进行重写
  4. Redis重启时,可以加载AOF文件进行数据恢复

6、探索AOF文件

首先我们在redis.conf配置中开启appendonly 功能。

image

然后重启Redis服务。

image

最后我们打开Redis的客户添加一些数据。

image

接下来看一下aof文件:

image

7、AOF优缺点

--优点

  • 安全性相对RDB方式高很多。
  • AOF文件是一个只进行追加的日志文件,所以不需要写入seek,即使由于某些原因(磁盘空间已满,写的过程中宕机等等)未执行完整的写入命令,你也也可使用redis-check-aof工具修复这些问题。
  • AOF 文件的格式可读性较强,这也为使用者提供了更灵活的处理方式。例如,如果我们不小心错用了 FLUSHALL 命令,在重写还没进行时,我们可以手工将最后的 FLUSHALL 命令去掉,然后再使用 AOF 来恢复数据。

--缺点

  • 对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。
  • 效率相对RDB方式低很多。
  • 根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB 。 在一般情况下, 每秒 fsync 的性能依然非常高, 而关闭 fsync 可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间(latency)。

8、AOF 恢复/修复

正常恢复:将有数据的aof文件复制一份保存到对应目录(config get dir),重启 Redis 之后就会进行 AOF 文件的载入。

异常修复:redis-check-aof --fix appendonly.aof 进行修复

9、如何选择使用哪种持久化方式?

一般来说, 如果对数据的安全性要求非常高的话,你应该同时使用两种持久化功能。

如果你非常关心你的数据, 但仍然可以承受数分钟以内的数据丢失, 那么你可以只使用 RDB 持久化。

有很多用户都只使用 AOF 持久化, 但我们并不推荐这种方式: 因为定时生成 RDB 快照(snapshot)非常便于进行数据库备份, 并且 RDB 恢复数据集的速度也要比 AOF 恢复的速度要快, 除此之外, 使用 RDB 还可以避免之前提到的 AOF 程序的 bug 。

10、RDB-AOF混合持久化

这个功能是Redis4.0之后才支持。使用RDB-AOF混合持久化的优缺点如下:

1--优点:

混合持久化结合了RDB持久化 和 AOF 持久化的优点,采取了rdb的文件小易于灾难恢复,同时结合AOF,增量的数据以AOF方式保存了,数据更少的丢失。

2--缺点:

兼容性差,一旦开启了混合持久化,在4.0之前版本都不识别该aof文件,同时由于前部分是RDB格式,需要专业的工具来阅读,因为是二进制,所以阅读性较差。

3--原理(先掌握RDB和AOP方式):

混合持久化也是通过bgrewriteaof完成的,所以基本流程和上述一样。不同的是当开启混合模式时,fork出的子进程先将共享的内存副本全量以RDB的方式写入aof。这样提高了速度也极大的缩小了aof文件(毕竟都是二进制)。写完还是通知主进程,然后再将重写缓冲区的内容以AOF方式写入到文件,然后替换旧的aof文件。也就是说这种模式下的aof文件发生rewrite后前半部分是rdb格式(REDIS开头的二进制数据),后半部分是正常的aof追加的命令(重写缓冲区里的)。

4--二者混用数据恢复优先选择谁:

会优先看是否存在aof文件,若存在则先按照aof文件恢复,因为aof毕竟比rdb全。若aof不存在,则才会查找rdb是否存在。这是默认的机制。毕竟aof文件也rewrite成rdb二进制格式,文件小,易于回复。所以redis会优先采取aof。

参考链接:

  1. 搞懂Redis RDB和AOF持久化及工作原理
  2. 彻底搞懂Redis持久化之AOF原理
作者: 唐浩荣
本文版权归作者和博客园共有,欢迎转载,但是转载需在博客的合适位置给出原文链接,否则保留追究法律责任的权利。
原文地址:https://www.cnblogs.com/tanghaorong/p/14300631.html