文章目录
- 一、AOF基础配置
-
- 1、开启AOF持久化
- 2、文件名配置
- 3、混合式持久化
- [4、AOF 文件目录配置](#4、AOF 文件目录配置)
- 二、AOF文件格式
- 三、Rewrite机制
- [四、AOF 优化配置](#四、AOF 优化配置)
- 五、AOF持久化过程
- [六、RDB 与 AOF 对比](#六、RDB 与 AOF 对比)
本文参考:
Redis学习汇总(已完结)
Redis超详细入门教程(基础篇)
Redis视频从入门到高级,redis视频教程详解,Redis一课在手,别无所求
黑马程序员Redis入门到实战教程,深度透析redis底层原理
AOF,Append Only File,是指 Redis 将每一次的写操作都以日志的形式记录到一个 AOF文件中的持久化技术。当需要恢复内存数据时,将这些写操作重新执行一次,便会恢复到之前的内存数据状态。
一、AOF基础配置
1、开启AOF持久化
默认情况下 AOF 持久化是没有开启的,redis使用的是RDB持久化,可以通过修改配置文件中的 appendonly 属性为yes开启AOF持久化。
2、文件名配置
Redis 7 在这里发生了重大变化。原来只有一个 appendonly.aof 文件,现在具有多个文件,包括以下三类:
● 基本文件(base):可以是RDB 格式也可以是AOF 格式。其存放的内容是由 RDB 转为 AOF 当时内存的快照数据。该文件可以有多个。
● 增量文件(incr):以操作日志形式记录转为 AOF 后的写入操作。该文件可以有多个。
● 清单文件(manifest):用于维护 AOF 文件的创建顺序,保障激活时的应用顺序。该文件只有一个。
3、混合式持久化
对于基本文件可以是 RDF 格式也可以是 AOF 格式。通过 aof-use-rdb-preamble
属性可以选择。其默认值为yes,即默认 AOF 持久化的基本文件为rdb 格式文件,也就是默认采用混合式持久化。
4、AOF 文件目录配置
为了方便管理,可以专门为 AOF 持久化文件指定存放目录。目录名由 appenddirname属性指定,存放在redis.conf 配置文件的 dir 属性指定的目录,默认为 Redis 安装目录。上述指定了appenddirname的值为appendonlydir,则会在Redis的安装目录下新建一个appendonlydir文件夹存放AOF持久化文件。
二、AOF文件格式
AOF 文件包含三类文件:基本文件、增量文件与清单文件。其中基本文件一般为rdb 格式,在前面已经研究过了。下面来看一下增量文件与清单文件的内容格式。
1、Redis协议
增量文件的扩展名为.aof,采用 AOF 格式。AOF 格式其实就是Redis 通讯协议格式,AOF 持久化文件的本质就是基于 Redis 通讯协议的文本,将命令以纯文本的方式写入到文件中。
Redis 协议规定,Redis 文本是以行来划分,每行以\r\n 结束。每一行都有一个消息头,以表示消息类型。消息头由六种不同的符号表示,其意义如下:
● (+) 表示一个正确的状态信息;
● (-) 表示一个错误信息;
● (*) 表示消息体总共有多少行,不包括当前行;
● ($) 表示下一行消息数据的长度,不包括换行符长度\r\n;
● (空) 表示一个消息数据;
● (:) 表示返回一个数值。
2、查看AOF文件
打开 appendonly.aof.1.incr.aof 文件,可以看到如下格式内容。
以上内容中框起来的是三条命令。一条数据库切换命令 SELECT 0,两条 set 命令。它们的意义如下:
参数值 | 含义解释 |
---|---|
*2 | -- 表示当前命令包含 2 个参数 |
$6 | -- 表示第 1 个参数包含 6 个字符 |
SELECT | -- 第 1 个参数 |
$1 | -- 表示第 2 个参数包含 1 个字符 |
0 | -- 第 2 个参数 |
*3 | -- 表示当前命令包含 3 个参数 |
$3 | -- 表示第 1 个参数包含 3 个字符 |
set | -- 第 1 个参数 |
$3 | -- 表示第 2 个参数包含 3 个字符 |
k11 | -- 第 2 个参数 |
$3 | -- 表示第 3 个参数包含 2 个字符 |
v11 | -- 第 3 个参数 |
3、查看清单文件
打开清单文件 appendonly.aof.manifest,查看其内容如下:
该文件首先会按照 seq 序号列举出所有基本文件,基本文件 type 类型为 b,然后再按照 seq 序号再列举出所有增量文件,增量文件 type 类型为 i。
对于 Redis 启动时的数据恢复,也会按照该文件由上到下依次加载它们中的数据。
三、Rewrite机制
通过前面的学习可以知道,Redis随着写入数据的增多,AOF文件中写入的内容也会越来越多,随着使用时间的推移,AOF 文件会越来越大。为了防止 AOF 文件由于太大而占用大量的磁盘空间,降低性能, Redis 引入了 Rewrite 机制来对 AOF 文件进行压缩。
1、何为rewrite
所谓 Rewrite 其实就是对 AOF 文件进行重写整理的过程。当 Rewrite 开启后,主进程 redis-server会创建出一个子进程 bgrewriteaof,由该子进程完成 rewrite 过程。其首先对现有 aof 文件进行 rewrite 计算,将计算结果写入到一个临时文件,写入完毕后,再 rename 该临时文件为原 aof文件名,覆盖原有文件。
2、rewrite计算
rewrite 计算也称为rewrite 策略。rewrite 计算遵循以下策略:
● 读操作命令不写入文件;
● 无效命令不写入文件;
● 过期数据不写入文件;
● 多条命令合并写入文件。
通过对aof文件进行rewrite计算整理,aof文件中的内容会大大减少,从而减轻了磁盘占用,当rewrite计算完成后,这个新的小aof文件会通过重命名覆盖掉之前的大aof文件。
3、手动开启rewrite
Rewrite 过程的执行有两种方式。一种是通过 bgrewriteaof
命令手动开启,一种是通过设置条件自动开启。
手动开启rewrite:
该命令会使主进程redis-server 创建出一个子进程 bgrewriteaof,由该子进程完成 rewrite过程。而在rewrite 期间,redis-server 仍是可以对外提供读写服务的。
4、自动开启rewrite
手动方式需要人办干预,所以一般采用自动方式。由于 Rewrite 过程是一个计算过程,需要消耗大量系统资源,会降低系统性能。所以,Rewrite 过程并不是随时随地任意开启的,而是通过设置一些条件,当满足条件后才会启动,以降低对性能的影响。这里的条件可以通过redis的配置文件进行设置。
下面是配置文件中对于 Rewrite 自动启动条件的设置。
● auto-aof-rewrite-percentage
:开启 rewrite 的增大比例,默认 100%。即当aof增量文件占用量增大一倍时启动rewrite;若指定为 0,表示禁用自动 rewrite。
● auto-aof-rewrite-min-size
:开启 rewrite 的AOF 文件最小值,默认 64M。相当于设定一个阈值,只有超过64M的aof文件才会进行rewrite;该值的设置主要是为了防止小AOF 文件在增长的过程中一直被 rewrite,从而导致性能下降。
自动重写 AOF 文件。当 AOF 日志文件大小增长到指定的百分比时,Redis 主进程redis-server 会 fork 出一个子进程 bgrewriteaof 来完成 rewrite 过程。
其工作原理如下:Redis 会记住最新 rewrite 后的 AOF 文件大小作为基本大小,如果从主机启动后就没有发生过重写,则基本大小就使用启动时 AOF 的大小。
如果当前 AOF 文件大于基本大小的配置文件中指定的百分比阈值,且当前 AOF 文件大于配置文件中指定的最小阈值,则会触发 rewrite。
四、AOF 优化配置
1、appendfsync
实际上,在执行了写操作命令后,该命令会首先写入到 aof_buf 中,这是一个缓冲区,而后会再持久化到磁盘AOF文件中,当客户端提交了写操作命令后,该命令就会写入到 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()系统函数来完成同步。该策略兼顾到了性能与安全,是一种折中方案。
2、no-appendfsync-on-rewrite
该属性用于指定,当 AOF fsync 策略设置为 always
或everysec
,当主进程创建了子进程正在执行 bgsave
或 bgrewriteaof
时,主进程是否不调用 fsync()
来做数据同步。设置为 no
,双重否定即肯定,主进程会调用 fsync()
做同步。而yes
则不会调用 fsync()
做数据同步。
如果调用fsync()
,在需要同步的数据量非常大时,会阻塞主进程对外提供服务,即会存在延迟问题。如果不调用 fsync()
,则 AOF fsync 策略相当于设置为了 no,可能会存在 30 秒数据丢失的风险。
这里比较绕,再引入一段解释。
关于aof的原理,类似于预写日志,不再解释。其中几个选项如下:
①
appendfsync always
:总是写入aof文件,并完成磁盘同步②
appendfsync everysec
:每一秒写入aof文件,并完成磁盘同步 appendfsync no:自己不管同步,交给操作系统。可见,从持久化角度讲,always是最安全的。从效率上讲,no是最快的。而redis默认设置进行了折中,选择了everysec。合情合理。使用bgrewriteaof机制,在一个子进程中进行aof的重写,从而不阻塞主进程对其余命令的处理,同时解决了aof文件过大问题。
现在问题出现了,同时在执行bgrewriteaof操作和主进程写aof文件的操作,两者都会操作磁盘,而bgrewriteaof往往会涉及大量磁盘操作,这样就会造成主进程在写aof文件的时候出现阻塞的情形,现在no-appendfsync-on-rewrite参数出场了。
如果该参数设置为no,是最安全的方式,不会丢失数据,但是要忍受阻塞的问题。如果设置为 yes呢?这就相当于将appendfsync设置为no,这说明并没有执行磁盘操作,只是写入了缓冲区,因此这样并不会造成阻塞(因为没有竞争磁盘),但是如果这个时候redis挂掉,就会丢失数据。
丢失多少数据呢?在Iinux的操作系统的默认设置下,最多会丢失30s的数据。因此,如果应用系统无法忍受延迟,而可以容忍少量的数据丢失,则设置为yes。如果应用系统无法忍受数据丢失,则设置为no。
3、aof-rewrite-incremental-fsync
前面说过 bgrewriteaof 在执行过程中先将 rewrite 计算的结果写入到一个临时文件中,其实在写入临时文件的之前会先写到 aof_rewrite_buf 缓存中,然后当缓存中数据达到一定量后就会调用 fsync()
进行刷盘操作,即数据同步,将数据写入到临时文件。该属性用于控制 fsync()
每次刷盘的数据量最大不超过 4MB。这样可以避免由于单次刷盘量过大而引发长时间阻塞。
4、aof-load-truncated
在进行 AOF 持久化过程中可能会出现系统突然宕机的情况,此时写入到 AOF 文件中的最后一条数据可能会不完整。当主机启动后,Redis 在 AOF 文件不完整的情况下是否可以启动,取决于属性aof-load-truncated 的设置。其值为:
● yes
:AOF 文件最后不完整的数据直接从 AOF 文件中截断删除,不影响Redis 的启动。
● no
:AOF 文件最后不完整的数据不可以被截断删除,Redis 无法启动。
如果是AOF文件中间出现损坏数据不完整的情况,没有办法,Redis无法启动,此时可以使用redis-check-aof --fix
进行修复,但不会完好如初,而是将其从损坏部分开始截断,只保留前半部分完好的,此时会造成数据丢失。
5、aof-timestamp-enabeld
该属性设置为yes 则会开启在 AOF 文件中增加时间戳的显示功能,可方便按照时间对数据进行恢复。但该方式可能会与 AOF 解析器不兼容,所以默认值为 no,不开启。
五、AOF持久化过程
AOF 详细的持久化过程如下:
-
Redis 接收到的写操作命令并不是直接追加到磁盘的AOF 文件的,而是将每一条写命令按照redis 通讯协议格式暂时添加到 AOF 缓冲区
aof_buf
。 -
根据设置的数据同步策略,当同步条件满足时,再将缓冲区中的数据一次性写入磁盘的AOF 文件,以减少磁盘 IO 次数,提高性能。
-
当磁盘的 AOF 文件大小达到了rewrite 条件时,redis-server 主进程会fork 出一个子进程bgrewriteaof,由该子进程完成 rewrite 过程。
-
子进程 bgrewriteaof 首先对该磁盘 AOF 文件进行 rewrite 计算,将计算结果写入到一个临时文件,全部写入完毕后,再 rename 该临时文件为磁盘文件的原名称,覆盖原文件。
-
如果在 rewrite 过程中又有写操作命令追加,那么这些数据会暂时写入 aof_rewrite_buf缓冲区。等将全部rewrite 计算结果写入临时文件后,会先将 aof_rewrite_buf 缓冲区中的数据写入临时文件,然后再rename 为磁盘文件的原名称,覆盖原文件。
六、RDB 与 AOF 对比
RDB(Redis Database)持久化技术和AOF(Append-Only File)持久化技术是Redis用于数据持久化的两种主要方式。它们各自具有一些优点和不足:
RDB持久化技术的优点:
- 高效性:RDB是一种紧凑且高效的快照机制,它将Redis在某个时间点的数据状态保存到磁盘上的一个二进制文件中。这种方式非常适合用于定期备份和数据迁移。
- 性能较好:由于RDB是通过生成一个快照来进行持久化,所以它对系统的性能影响较小。在某些情况下,可以使用RDB来实现更好的性能和响应时间。
- 容易恢复:将Redis恢复到RDB快照所代表的状态非常简单,只需将快照文件加载到Redis服务器即可。
RDB持久化技术的不足:
- 数据丢失风险:由于RDB是基于某个时间点的快照,如果Redis发生故障或意外关闭,那么在最后一次生成快照之后的所有更新将会丢失。
- 不适合实时数据:RDB是定期生成快照的方式,因此在两次快照之间的数据更新都无法被持久化。如果需要保证实时数据的一致性,RDB可能不太适合。
AOF持久化技术的优点:
- 可靠性:AOF以日志追加的方式记录每个写操作命令,这意味着即使Redis发生故障或意外关闭,也可以通过重新执行AOF日志文件中的命令来还原数据,减少了数据丢失的风险。
- 数据完整性:AOF记录的是写操作命令,因此它可以准确地反映出Redis服务器接收到的每一个写操作,包括过期、删除和修改等操作,从而保证了数据的完整性。
- 实时性:AOF支持更频繁的持久化操作,可以通过配置不同的策略来控制写入AOF日志文件的频率,从而实现更高的数据实时性。
AOF持久化技术的不足:
- 文件体积较大:AOF日志文件通常会比RDB快照文件大,因为它需要记录每个写操作的详细信息。这可能会导致AOF文件的体积相对较大,占用更多的磁盘空间。
- 恢复速度较慢:由于AOF记录了每个写操作命令,所以在恢复时需要重新执行所有的命令,这可能导致恢复速度较慢。
- 对性能的影响:AOF持久化可能对Redis的写入性能产生一定的影响,特别是在频繁写入的情况下。为了平衡性能和持久化的需求,可以通过调整AOF的同步策略来进行优化。
综上所述,RDB持久化技术适用于定期备份和数据迁移,具有高效性和较好的性能,但可能存在数据丢失的风险。而AOF持久化技术以日志追加的方式记录每个写操作命令,具有较高的可靠性和实时性,但可能会占用更多的磁盘空间,并对写入性能产生一定的影响。根据实际需求和场景,可以选择合适的持久化方式或结合两种方式来使用。
● 官方推荐使用RDB 与 AOF 混合式持久化。
● 若对数据安全性要求不高,则推荐使用纯 RDB 持久化方式。
● 不推荐使用纯 AOF 持久化方式。
● 若 Redis 仅用于缓存,则无需使用任何持久化技术。