目录
1、AOF日志
2、AOF 的执行顺序与潜在风险
3、如何优化 AOF?(写入策略)
4、AOF重写机制(防止日志文件无限增长)
1、AOF日志
想象一下,Redis 每次执行写操作的时候,都把这些操作以追加的方式写入一个文件中,然后当你重启 Redis 时,Redis 会从这个文件里读取命令并重新执行,这样就相当于恢复了缓存的数据。这就是 Redis 的 AOF 持久化功能——它专门用来记录写操作(读操作是不会记录的,因为读操作没必要重放)。
默认情况下,AOF 是关闭的(Redis 6.0 之后已经默认是开启了)。如果你想用它,需要去修改 Redis 的配置文件 redis.conf
,把相应的参数打开。只有同步到磁盘中才算持久化保存了,否则依然存在数据丢失的风险,比如说:系统内核缓存区的数据还未同步,磁盘机器就宕机了,那这部分数据就算丢失了。
# 是否开启 AOF 持久化 (默认值: no)
# 改为 yes 表示开启 AOF 持久化功能
appendonly yes
# AOF 持久化文件的名称 (默认值: appendonly.aof)
# 可以自定义 AOF 文件的名称
appendfilename "appendonly.aof"
AOF 日志就是一个普通的文本文件,里面记录的都是命令,比如执行 set name xiaotao
,日志里的内容大概是这样的:
*3
$3
set
$4
name
$7
xiaotao
这些奇怪的符号看上去可能有点复杂,其实很好理解。*3
表示这个命令由三部分组成,每部分的内容前都有一个 $
和一个数字,比如 $3
后面是 set
,意思是这个部分的内容有 3 个字节(也就是 set
这个命令有 3 个字符)。
2、AOF 的执行顺序与潜在风险
执行顺序:Redis 先执行写操作,再把命令记录到 AOF 日志里,这样做有两个好处:
- 避免额外的检查开销:如果先写日志再执行命令,可能会把错误的命令写进日志,那在数据恢复时就会出错。先执行命令再记录日志,确保写进日志的命令都是正确的。
- 减少写操作的阻塞:因为日志是在命令成功执行后才写入的,所以不会影响当前的写操作。
潜在风险:虽然 AOF 很强大,但也有一些风险:
- 数据丢失风险:因为写命令和写日志是两个步骤,如果 Redis 还没来得及把命令写入日志就宕机了,这部分数据就会丢失。
- 阻塞风险:写日志的操作是在主进程完成的,如果硬盘压力大,写日志的速度变慢,就可能阻塞后续的命令执行。
3、如何优化 AOF?(写入策略)
在 Redis 中,AOF 是通过一种「先缓存、后写盘」的方式来保存数据。写操作完成后,命令会被追加到 server.aof_buf
缓冲区中,然后通过 write()
系统调用将缓冲区数据写入 AOF 文件。不过,数据并没有直接写到硬盘,而是暂时放在操作系统的内核缓冲区(page cache
)中,之后由操作系统决定什么时候把这些数据写入硬盘。
AOF潜在风险的本质都跟 AOF 日志什么时候写入硬盘有关。所以 Redis 提供了几种不同的写入策略,由 redis.conf
配置文件中的 appendfsync
配置项控制,你可以根据需求来调整。这三种策略是:
(一)always(总是)
- 含义:每次写操作命令执行完后,立即将 AOF 日志数据写入硬盘。
- 优点:数据几乎不会丢失,因为每次操作都会马上保存到硬盘。
- 缺点:性能最差,因为频繁的硬盘操作会拖慢 Redis 的主进程。
(二)everysec(每秒)
- 含义:写操作执行后,命令会先被写入到 AOF 文件,但每隔一秒才同步到硬盘。
- 优点:在性能和数据安全之间做了折中,减少了频繁写盘带来的性能损耗,同时每秒进行一次写盘,丢失数据的风险也相对较小。
- 缺点:如果 Redis 在这 1 秒内宕机,最后的写操作数据可能会丢失。
(三)no(不控制)
- 含义:不由 Redis 控制写盘时机,而是交给操作系统处理,数据写入内核缓冲区后,操作系统会自行决定什么时候写入硬盘。
- 优点:性能最好,因为 Redis 不会干涉写盘,减少了 Redis 主进程的负担。
- 缺点:数据丢失的可能性更大,因为操作系统决定写入的时机不可预知,如果宕机,可能会丢失大量数据。
三种策略的优缺点对比
策略 | 数据安全性 | 性能表现 | 适用场景 |
---|---|---|---|
always | 数据最安全,几乎不丢失 | 性能最差 | 适合要求高可靠性的数据存储场景 |
everysec | 数据丢失量最多 1 秒 | 性能较好,折中方案 | 大多数场景适用,平衡性能和数据丢失风险 |
no | 可能丢失较多数据 | 性能最好 | 适合高性能要求,不介意数据丢失的场景 |
所以要根据场景来选择写入策略
- 如果你的系统对性能要求高,可以选择
no
策略,最大化提升 Redis 的执行效率。 - 如果你不能容忍任何数据丢失,那就选择
always
策略,确保每次操作都立即写入硬盘。 - 对大多数业务场景来说,everysec 是一个比较好的折中选择:它既能保持不错的性能,又能在保证数据安全方面做得比较好,只是可能会丢失 1 秒内的数据。
4、AOF重写机制(防止日志文件无限增长)
在 Redis 中,AOF 持久化会不断记录写操作命令到一个文件中,随着时间的推移,这个文件的大小会越来越大。如果 AOF 文件太大,可能会带来一些问题,例如性能问题:文件越大,Redis 重启时需要花费更多时间去读取 AOF 文件以恢复数据,导致恢复速度变慢。
为了解决这个问题,Redis 提供了 AOF 重写机制,当 AOF 文件超过设定的阈值后,Redis 会自动对 AOF 文件进行压缩。
(一)AOF 重写的原理:
AOF 重写机制是在重写时,读取当前数据库中的所有键值对,然后将每一个键值对用一条命令记录到「新的 AOF 文件」,等到全部记录完后,就将新的 AOF 文件替换掉现有的 AOF 文件。所以,AOF 重写机制并不是直接修改现有的 AOF 文件,而是创建一个新的 AOF 文件,这个新的文件会根据当前 Redis 数据库的状态来生成。
- 从数据库读取当前状态:重写时,Redis 会读取当前数据库中的所有键值对。
- 记录最新状态:然后,每个键值对只会用一条命令记录到新的 AOF 文件中。这就避免了历史的命令积累,只记录当前的最新数据状态。
举个例子:
假设在没有重写之前,我们执行了两条命令:
set name xiaotao
set name xiaotaostudy
这两条命令会依次被记录到 AOF 文件中。但是在 AOF 重写之后,Redis 会只保留最新的键值对状态,即用一条命令 set name xiaotaostudy
来替换之前的两条命令。因为第一条命令已经是历史命令,最新的值已经覆盖掉它了,没必要保留。
通过这种方式,AOF 文件的体积大大减少了,因为它只保存了数据的最终状态,而不是所有的修改历史。
重写到新的 AOF 文件中,而不是直接对旧 AOF 文件修改的好处
- 数据安全:如果重写过程中发生了错误,比如进程挂了,现有的 AOF 文件不会被影响,因为 Redis 还没有用新的文件替换它。
- 避免污染现有文件:如果直接修改现有文件,一旦发生错误,文件可能会损坏,无法用于数据恢复。
(2)重写期间的同步机制
由于 AOF 重写涉及到大量的写入操作,直接在主进程中进行重写可能会影响 Redis 处理命令的效率。为了避免这种情况,Redis 将 AOF 重写的操作放在子进程中执行,主进程继续处理正常的命令请求。
- AOF 重写缓冲区:当子进程创建新的 AOF 文件时,Redis 主进程会将所有新执行的写命令记录到一个叫做 AOF 重写缓冲区的地方。这是为了确保在重写过程中,数据的修改不会丢失。
- 同步数据:当子进程完成新的 AOF 文件创建后,Redis 会把重写期间存放在缓冲区的写命令追加到新的 AOF 文件末尾。这确保了新文件和当前数据库的状态完全一致。
- 文件替换:新 AOF 文件创建完成并同步后,Redis 将旧的 AOF 文件替换为新的文件,完成整个重写过程。
(三)手动或自动触发 AOF 重写
-
手动触发:你可以通过
BGREWRITEAOF
命令手动执行 AOF 重写。 -
自动触发:Redis 还支持自动触发 AOF 重写,通过配置以下两个参数实现:
-
auto-aof-rewrite-min-size:AOF 文件的最小触发大小。只有当文件大小超过这个值时,才会触发重写。默认值是 64 MB。
-
auto-aof-rewrite-percentage:AOF 文件大小增长百分比。如果当前 AOF 文件的大小相较于上一次重写后的文件大小,增加了设定的百分比值,Redis 会触发自动重写。默认是 100%,表示文件大小翻倍时重写。
-
推荐:
【MySQL】常见的SQL优化方式(二)-CSDN博客https://blog.csdn.net/m0_65277261/article/details/142610165?spm=1001.2014.3001.5501【MySQL】常见的SQL优化方式(一)_mysql优化-CSDN博客https://blog.csdn.net/m0_65277261/article/details/142376280?spm=1001.2014.3001.5501