Redis持久化AOF

什么是 AOF?

AOF 是 Append Only File 的意思,它是指 Redis 在持久化数据到硬盘的时候是以日志的形式来记录每个写操作,并保存到磁盘的一个文件中,这个文件的名字默认叫 appendonly.aof

AOF 持久化的原理

理论上说,只要我们保存了所有可能修改 Redis 内存数据的命令(也就是写命令),那么根据这些保存的写命令,我们可以重新恢复 Redis 的内存状态。AOF 持久化正是利用这个原理来实现数据的持久化与数据的恢复的。

Redis持久化AOF

AOF 配置

为了打开 AOF 持久化的功能,我们只需要将 redis.conf 配置文件中的appendonly配置选项设置为yes即可。涉及 AOF 持久化的几个常用配置如下所示:

  • appendonly yes                                   是否打开 AOF 持久化功能
  • appendfilename "appendonly.aof"       AOF 文件名称
  • appendfsync everysec                        同步频率,可选配置如表1所示

appendfsync 选项及同步频率

选项 同步频率
always 每个 Redis 命令都要同步写入硬盘。这样会严重降低 Redis 的性能
everysec 每秒执行一次同步,显式地将多个写命令同步到硬盘
no 让操作系统来决定应该何时进行同步

AOF缓存区的同步文件策略由参数appendfsync控制,各个值的含义如下:

  • always:命令写入aof_buf后立即调用系统fsync操作同步到AOF文件,fsync完成后线程返回。这种情况下,每次有写命令都要同步到AOF文件,硬盘IO成为性能瓶颈,Redis只能支持大约几百TPS写入,严重降低了Redis的性能;即便是使用固态硬盘(SSD),每秒大约也只能处理几万个命令,而且会大大降低SSD的寿命。
  • no:命令写入aof_buf后调用系统write操作,不对AOF文件做fsync同步;同步由操作系统负责,通常同步周期为30秒。这种情况下,文件同步的时间不可控,且缓冲区中堆积的数据会很多,数据安全性无法保证。
  • everysec:命令写入aof_buf后调用系统write操作,write完成后线程返回;fsync同步文件操作由专门的线程每秒调用一次。everysec是前述两种策略的折中,是性能和数据安全性的平衡,因此是Redis的默认配置,也是我们推荐的配置。 

AOF执行流程

由于需要记录Redis的每条写命令,下面介绍AOF的执行流程。
AOF的执行流程包括:

  • 命令追加(append):将Redis的写命令追加到缓冲区aof_buf;
  • 文件写入(write)和文件同步(sync):根据不同的同步策略将aof_buf中的内容同步到硬盘;
  • 文件重写(rewrite):定期重写AOF文件,达到压缩的目的。

AOF 文件的生成过程具体包括命令追加,文件写入,文件重写三个步骤。

  1. Redis 打开 AOF 持久化功能后,Redis 在执行完一个写命令后,都会将执行的写命令追回到 Redis 内部的缓冲区的末尾。主要是为了避免每次有写命令都直接写入硬盘,导致硬盘IO成为Redis负载的瓶颈。这个过程是命令的追加过程。
  2. 接下来,缓冲区的写命令会被写入到 AOF 文件,这一过程是文件写入过程。对于操作系统来说,调用write函数并不会立刻将数据写入到硬盘,为了将数据真正写入硬盘,还需要调用fsync函数,调用fsync函数即是文件同步的过程。只有经过文件同步过程,AOF 文件才在硬盘中真正保存了 Redis 的写命令。appendfsync 配置选项正是用来配置将写命令同步到文件的频率的,各个选项的值的含义如上表所示。

文件重写

       随着时间流逝,Redis服务器执行的写命令越来越多,AOF文件也会越来越大;过大的AOF文件不仅会影响服务器的正常运行,也会导致数据恢复需要的时间过长。

       文件重写是指定期重写AOF文件,减小AOF文件的体积。需要注意的是,AOF重写是把Redis进程内的数据转化为写命令,同步到新的AOF文件;不会对旧的AOF文件进行任何读取、写入操作! 重写 AOF 并删除旧 AOF 文件的过程将会对 Redis 的性能造成较大的影响。

       关于文件重写需要注意的另一点是:对于AOF持久化来说,文件重写虽然是强烈推荐的,但并不是必须的;即使没有文件重写,数据也可以被持久化并在Redis启动的时候导入;因此在一些实现中,会关闭自动的文件重写,然后通过定时任务在每天的某一时刻定时执行。

       为此,Redis 提供两个配置选项来对 AOF 重写进行配置。

  • auto-aof-rewrite-percentage
  • auto-aof-rewrite-min-size

       auto-aof-rewrite-percentage配置当 AOF 文件需要比旧 AOF 文件增大多少时才进行 AOF 重写,而auto-aof-rewrite-min-size则配置当 AOF 文件需要达到多大体积时才进行 AOF 重写。只有这两个配置的条件都达到时,才会进行 AOF 重写。

文件重写之所以能够压缩AOF文件,原因在于:

  • 过期的数据不再写入文件
  • 无效的命令不再写入文件:如有些数据被重复设值(set mykey v1, set mykey v2)、有些数据被删除了(sadd myset v1, del myset)等等
  • 多条命令可以合并为一个:如sadd myset v1, sadd myset v2, sadd myset v3可以合并为sadd myset v1 v2 v3。不过为了防止单条命令过大造成客户端缓冲区溢出,对于list、set、hash、zset类型的key,并不一定只使用一条命令;而是以某个常量为界将命令拆分为多条。这个常量在redis.h/REDIS_AOF_REWRITE_ITEMS_PER_CMD中定义,不可更改,3.0版本中值是64。

AOF常用配置总结

下面是AOF常用的配置项,以及默认值;前面介绍过的这里不再详细介绍。

  • appendonly no:是否开启AOF
  • appendfilename “appendonly.aof”:AOF文件名
  • dir ./:RDB文件和AOF文件所在目录
  • appendfsync everysec:fsync持久化策略
  • no-appendfsync-on-rewrite no:AOF重写期间是否禁止fsync;如果开启该选项,可以减轻文件重写时CPU和硬盘的负载(尤其是硬盘),但是可能会丢失AOF重写期间的数据;需要在负载和安全性之间进行平衡
  • auto-aof-rewrite-percentage 100:文件重写触发条件之一
  • auto-aof-rewrite-min-size 64mb:文件重写触发提交之一
  • aof-load-truncated yes:如果AOF文件结尾损坏,Redis启动时是否仍载入AOF文件

AOF 的优点

  1. AOF 持久化的方法提供了多种的同步频率,即使使用默认的同步频率每秒同步一次,Redis 最多也就丢失 1 秒的数据而已。
  2.  AOF 文件使用 Redis 命令追加的形式来构造,因此,即使 Redis 只能向 AOF 文件写入命令的片断,使用 redis-check-aof 工具也很容易修正 AOF 文件。
  3. AOF 文件的格式可读性较强,这也为使用者提供了更灵活的处理方式。例如,如果我们不小心错用了 FLUSHALL 命令,在重写还没进行时,我们可以手工将最后的 FLUSHALL 命令去掉,然后再使用 AOF 来恢复数据。

AOF 的缺点

  1. 对于具有相同数据的的 Redis,AOF 文件通常会比 RDB 文件体积更大。
  2. 虽然 AOF 提供了多种同步的频率,默认情况下,每秒同步一次的频率也具有较高的性能。但在 Redis 的负载较高时,RDB 比 AOF 具好更好的性能保证。
  3. RDB 使用快照的形式来持久化整个 Redis 数据,而 AOF 只是将每次执行的命令追加到 AOF 文件中,因此从理论上说,RDB 比 AOF 方式更健壮。官方文档也指出,AOF 的确也存在一些 BUG,这些 BUG 在 RDB 没有存在。!

方案选择与常见问题(重点)

        在介绍持久化策略之前,首先要明白无论是RDB还是AOF,持久化的开启都是要付出性能方面代价的:对于RDB持久化,一方面是bgsave在进行fork操作时Redis主进程会阻塞,另一方面,子进程向硬盘写数据也会带来IO压力;对于AOF持久化,向硬盘写数据的频率大大提高(everysec策略下为秒级),IO压力更大,甚至可能造成AOF追加阻塞问题(后面会详细介绍这种阻塞),此外,AOF文件的重写与RDB的bgsave类似,会有fork时的阻塞和子进程的IO压力问题。相对来说,由于AOF向硬盘中写数据的频率更高,因此对Redis主进程性能的影响会更大。

        实际生产环境中,根据数据量、应用对数据的安全要求、预算限制等不同情况,会有各种各样的持久化策略;如完全不使用任何持久化、使用RDB或AOF的一种,或同时开启RDB和AOF持久化等。此外,持久化的选择必须与Redis的主从策略一起考虑,因为主从复制与持久化同样具有数据备份的功能,而且主机master和从机slave可以独立的选择持久化方案。

如果同时启用 RDB 和 AOF 这两种策略,那么 Redis 会加载哪个文件?

答:会优先加载 appendonly.aof 文件中的数据,就算只有 dump.rdb 文件,没有 appendonly.aof 文件,redis 也不会加载 dump.rdb 文件中的数据。

那要不要只使用 AOF 呢?

答:建议不要,因为 RDB 更适合于备份数据库,快速重启,AOF 启动慢,执行效率也慢(因为要经常存盘)。
 

本文仅用于复习,转载于 https://blog.csdn.net/qq_35433716/article/details/82195106