Redis学习笔记(九)--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 策略设置为 alwayseverysec,当主进程创建了子进程正在执行 bgsavebgrewriteaof 时,主进程是否不调用 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 详细的持久化过程如下:

  1. Redis 接收到的写操作命令并不是直接追加到磁盘的AOF 文件的,而是将每一条写命令按照redis 通讯协议格式暂时添加到 AOF 缓冲区 aof_buf

  2. 根据设置的数据同步策略,当同步条件满足时,再将缓冲区中的数据一次性写入磁盘的AOF 文件,以减少磁盘 IO 次数,提高性能。

  3. 当磁盘的 AOF 文件大小达到了rewrite 条件时,redis-server 主进程会fork 出一个子进程bgrewriteaof,由该子进程完成 rewrite 过程。

  4. 子进程 bgrewriteaof 首先对该磁盘 AOF 文件进行 rewrite 计算,将计算结果写入到一个临时文件,全部写入完毕后,再 rename 该临时文件为磁盘文件的原名称,覆盖原文件。

  5. 如果在 rewrite 过程中又有写操作命令追加,那么这些数据会暂时写入 aof_rewrite_buf缓冲区。等将全部rewrite 计算结果写入临时文件后,会先将 aof_rewrite_buf 缓冲区中的数据写入临时文件,然后再rename 为磁盘文件的原名称,覆盖原文件。

六、RDB 与 AOF 对比

RDB(Redis Database)持久化技术和AOF(Append-Only File)持久化技术是Redis用于数据持久化的两种主要方式。它们各自具有一些优点和不足:

RDB持久化技术的优点:

  1. 高效性:RDB是一种紧凑且高效的快照机制,它将Redis在某个时间点的数据状态保存到磁盘上的一个二进制文件中。这种方式非常适合用于定期备份和数据迁移。
  2. 性能较好:由于RDB是通过生成一个快照来进行持久化,所以它对系统的性能影响较小。在某些情况下,可以使用RDB来实现更好的性能和响应时间。
  3. 容易恢复:将Redis恢复到RDB快照所代表的状态非常简单,只需将快照文件加载到Redis服务器即可。

RDB持久化技术的不足:

  1. 数据丢失风险:由于RDB是基于某个时间点的快照,如果Redis发生故障或意外关闭,那么在最后一次生成快照之后的所有更新将会丢失。
  2. 不适合实时数据:RDB是定期生成快照的方式,因此在两次快照之间的数据更新都无法被持久化。如果需要保证实时数据的一致性,RDB可能不太适合。

AOF持久化技术的优点:

  1. 可靠性:AOF以日志追加的方式记录每个写操作命令,这意味着即使Redis发生故障或意外关闭,也可以通过重新执行AOF日志文件中的命令来还原数据,减少了数据丢失的风险。
  2. 数据完整性:AOF记录的是写操作命令,因此它可以准确地反映出Redis服务器接收到的每一个写操作,包括过期、删除和修改等操作,从而保证了数据的完整性。
  3. 实时性:AOF支持更频繁的持久化操作,可以通过配置不同的策略来控制写入AOF日志文件的频率,从而实现更高的数据实时性。

AOF持久化技术的不足:

  1. 文件体积较大:AOF日志文件通常会比RDB快照文件大,因为它需要记录每个写操作的详细信息。这可能会导致AOF文件的体积相对较大,占用更多的磁盘空间。
  2. 恢复速度较慢:由于AOF记录了每个写操作命令,所以在恢复时需要重新执行所有的命令,这可能导致恢复速度较慢。
  3. 对性能的影响:AOF持久化可能对Redis的写入性能产生一定的影响,特别是在频繁写入的情况下。为了平衡性能和持久化的需求,可以通过调整AOF的同步策略来进行优化。

综上所述,RDB持久化技术适用于定期备份和数据迁移,具有高效性和较好的性能,但可能存在数据丢失的风险。而AOF持久化技术以日志追加的方式记录每个写操作命令,具有较高的可靠性和实时性,但可能会占用更多的磁盘空间,并对写入性能产生一定的影响。根据实际需求和场景,可以选择合适的持久化方式或结合两种方式来使用。

● 官方推荐使用RDB 与 AOF 混合式持久化。

● 若对数据安全性要求不高,则推荐使用纯 RDB 持久化方式。

● 不推荐使用纯 AOF 持久化方式。

● 若 Redis 仅用于缓存,则无需使用任何持久化技术。

相关推荐
VertexGeek19 分钟前
Rust学习(八):异常处理和宏编程:
学习·算法·rust
Yz987632 分钟前
hive的存储格式
大数据·数据库·数据仓库·hive·hadoop·数据库开发
wkj00134 分钟前
php操作redis
开发语言·redis·php
苏-言44 分钟前
Spring IOC实战指南:从零到一的构建过程
java·数据库·spring
运维&陈同学1 小时前
【zookeeper01】消息队列与微服务之zookeeper工作原理
运维·分布式·微服务·zookeeper·云原生·架构·消息队列
Ljw...1 小时前
索引(MySQL)
数据库·mysql·索引
时差9531 小时前
Flink Standalone集群模式安装部署
大数据·分布式·flink·部署
二进制_博客1 小时前
Flink学习连载文章4-flink中的各种转换操作
大数据·学习·flink
菠萝咕噜肉i1 小时前
超详细:Redis分布式锁
数据库·redis·分布式·缓存·分布式锁
长风清留扬1 小时前
一篇文章了解何为 “大数据治理“ 理论与实践
大数据·数据库·面试·数据治理