AOF持久化
AOF Append only FIle,指Redis将每一次的写操作以日志形式记录到一个AOF文件中的持久化技术。
需要恢复内存数据时,将这些写操作重新执行一次,就会恢复到之前的内存数据状态。
AOF基础配置
AOF的开启
sh
# 在Redis配置文件中配置如下:
appendonly yes
默认情况下此配置关闭。
文件名配置
sh
appendfilename "appendonly.aof"
Redis7 在这里发生了重大变化,原来只有一个appendonly.aof文件,现在具有了三类多个文件:
- 基本文件:可以是RDB格式也可以是AOF格式,其存放内容是由RDB转换为AOF当时内存的快照数据。该文件可以有多个。
- 增量文件:以操作日志形式记录转为AOF后的写入操作,该文件可以有多个。
- 清单文件:用于维护AOF文件的创建顺序,保证激活时的应用顺序。该文件只有一个。
混合持久化开启
sh
aof-use-rdb-preamble yes
对于基本文件可以是RDB格式也可以是AOF格式,通过aof-use-rdb-preamble属性可以设置。默认yes。
即默认AOF持久化的基本文件以rdb格式,也就是默认启用混合持久化。
AOF文件目录配置
sh
appenddirname "appendonlydir"
AOF持久化文件指定存放目录,默认为Redis安装目录。
AOF文件格式
AOF文件包含三类文件:基本文件、增量文件和清单文件。
基本文件一般是rdb格式,下面将解释增量文件和清单文件的内容格式。
Redis协议
增量文件扩展名为.aof,AOF格式就是Redis通讯协议格式,AOF文件的本质就是基于Redis通讯协议的文本,将命令以纯文本的方式写入到文件中。
Redis协议规定,Redis文本以行来划分,每行以\r\n结束,每一行都有一个消息头,表示消息类型,消息头有6种不同符号表示:
- (+):表示一个正确的状态信息
- (-):表示一个错误信息
- (*):表示消息体总共有多少行,不包括当前行
- ($):表示下一行消息数据的长度,不包括换行符长度\r\n
- (空):表示一个消息数据
- (:):表示返回一个数值
查看AOF文件
打开appendonly.aof.1.incr.aof 文件,可以看到如下格式内容:
以上内容有三条命令:一条数据库切换命令select 0,两条set命令。其意义如下:
sh
*2 # 表示当前命令包含2个参数
$6 # 表示第一个参数包含6个字符
select # 第一个参数
$1 # 表示第二个参数包含1个字符
0 # 第二个参数
*3 #表示当前命令包含3个参数
$3 # 表示第一个参数包含3个字符
set # 第一个参数
$3 #表示第二个参数包含3个字符
k11 #表示第二个参数
$3 #表示第三个参数包含3个字符
v11 #表示第三个参数
清单文件
打开清单文件appendonly.aof.manifest,查看其内容如下:
该文件会先安装seq序号列出所有基本文件,基本文件type类型为b,
再安装seq序号列出所有增量文件,增量文件type类型为i。
当Redis启动数据恢复,会按照该文件由上到下依次加载他们中的数据。
Rewrite机制
随着时间推移,AOF文件会越来越大,为了放置AOF文件过大占用大量的空间,降低性能,Redis引入了Rewrite机制对AOF文件进行压缩。
什么是Rewrite
Rewrite就是对AOF文件进行重写整理。
当Rewrite开启后,主进程redis-server创建一个子进程bgrewriteaof,该子进程完成Rewrite过程。
其首先对现有aof文件进行Rewrite计算,将计算结果写入到一个临时文件,写入完毕后,再rename该临时文件为aof文件,覆盖原有文件。
Rewrite计算
Rewrite计算也称Rewrite策略。Rewrite计算遵循以下策略:
- 读操作不写入文件
- 无效命令不写入文件(对同一个key多次写命令,只写入最新的指令)
- 过期数据不写入文件
- 多条命令合并写入文件
手动开启Rewrite
Rewrite开启有两种方式:bgrewriteaof命令手动开启;设置条件自动开启。
bgrewriteaof命令会使主进程redis-server创建出一个子进程bgrewriteaof,有此子进程完成rewrite过程。
在Rewrite期间,redis-server仍可以对外提供读写服务。
自动开启Rewrite
通过设置一些条件,当条件满足后才会开启。可在配置文件中对Rewrite自动启动条件设置:
- auto-aof-rewrite-percentage:开启rewrite的增大比例,默认100%。指定为0.表示禁用自动rewrite。
- auto-aof-rewrite-min-size:开启rewrite的AOF文件最小值,默认64M。该值的设置主要是为了放置小AOF文件被rewrite,从而导致性能下降。
当AOF日志文件大小增长到指定的百分比时,主进程redis-server创建出一个子进程bgrewriteaof来完成rewrite过程。
其工作原理如下:
Redis会记住最新rewrite后的AOF文件大小作为基本大小,
如果从主机启动后就没有发生过重写,基本大小就是启动时AOF的大小。
如果当前AOF文件大于基本大小的指定百分比阈值,且当前AOF文件大于配置文件中指定的最小阈值,则会触发rewrite。
AOF优化配置
appendfsync
当客户端提交写操作命令后,该命令就会写入到aof_buf中,而aof_buf中的数据持久化到AOF文件的过程称为数据同步。
何时将aof_buf的数据同步到AOF文件?
采用不同的数据同步策略,同时的时机是不同的,有三种策略:
- always:写操作命令写入到aof_buf后立即调用fsync()函数,将其追加到AOF文件 。该策略效率低,比较安全,不会丢失太多数据。 最多就是丢失刚刚执行的写操作。
- no:写操作命令写入到aof_buf后什么也不做,不会调用fsync()函数。由操作系统负责将aof_buf中的数据同步到磁盘 ,Linux系统默认同步周期是30秒,效率较高。
- everysec:默认策略 。写操作命令写入aof_buf后不直接调用fsync(),而是每秒调用一次fsync() 来完成同步。该策略兼顾性能与安全,是一种折中方案。
no-appendfsync-on-rewrite
该属性指定,当AOF fsync策略设置为always或everysec,当主进程创建子进程正在执行bgsave或bgrewriteaof时,主进程是否不调用fsync()来做数据同步。
设置为no,双重否定即肯定,主进程会调用fsync()做同步;
设置为yes,则不会调用fsync()做数据同步。
如果调用fsync(),在同步数据量非常大时,会阻塞主进程对外提供服务;
如果不调用fsync(),可能会存在30秒数据丢失风险。
aof-rewrite-incremental-fsync
当bgrewriteaof在执行时,先将rewrite计算结果写入到aof_rewrite_buf缓存中,当缓存数据达到一定量后就会调用fsync()进行刷盘操作,即数据同步。
该属性用户控制fsync()每次刷盘的数据量最大不超过4MB。这样可以避免由于单次刷盘量过大而引发长时间阻塞。
aof-load-truncated
在进行AOF持久化时,系统突然宕机,此时写入到AOF文件中的最后一条数据可能不完整,当主机启动后,Redis在AOF文件不完整的情况下是否可以启动,由aof-load-truncated设置。其值为:
- yes:AOF文件最后不完整的数据会被截断删除,不影响Redis启动。
- no:不删除不完整数据,Redis无法启动.
aof-timestamp-enabled
该属性设置为yes,会在AOF文件中显示时间戳,方便按照时间对数据进行恢复.
但是,该方式可能会与AOF解析器不兼容,所以默认为no,不开启.
AOF持久化过程
AOF持久化过程如下:
- Redis接收到写命令后将命令按照Redis通讯协议格式暂时添加到AOF缓冲区aof_buf。
- 根据数据同步策略,再将缓冲区的数据一次性写入磁盘的AOF文件,以减少io次数,提高性能。
- 当AOF文件达到rewrite条件时,redis-server主进程会fork一个子进程bgrewriteaof,由该子进程完成rewrite过程。
- 子进程先对AOF文件进行rewrite计算,将计算结果写入一个临时文件,全部写入完毕后,再rename该临时文件,覆盖原文件。
- 如果在rewrite过程种又有写命令追加,那么这些数据会写入aof_rewrite_buf缓冲区。等将rewrite计算结果写入临时文件后,会先将aof_rewrite_buf缓冲区的数据写入到临时文件,然后再rename成源文件名称,覆盖原文件。
RDB与AOF对比
| 优点 | 缺点 | |
|---|---|---|
| RDB | 文件小、恢复快 | 安全性差、写时复制会降低性能、RDB文件可读性差 |
| AOF | 安全性高、AOF文件可读性强 | 文件大、写操作影响性能、数据恢复慢 |
官方推荐使用RDB与AOF混合式持久化
如果数据安全性要求不高,推荐使用RDB方式
不推荐使用纯AOF方式
若Redis仅用作缓存,则无需使用任何持久化技术。