Redis AOF 持久化

Redis AOF 持久化

简介

AOF (Append Only File): the AOF persistence logs every write operation received by the server, that will be played again at server startup, reconstructing the original dataset. Commands are logged using the same format as the Redis protocol itself, in an append-only fashion. Redis is able to rewrite the log in the background when it gets too big.

作用

  • 以日志的形式来记录每个写操作,将 Redis 执行过的所有写指令记录下来(读操作不记录),只允许追加文件但不可以改写文件,redis 启动之初会读取该文件重新构建数据,换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作
  • 默认情况下,redis 是没有开启 AOF 的。开启 AOF 功能需要设置配置:appendonly yes
  • AOF 保存的是 appendonly.aof 文件

AOF 持久化工作流程

  • Client 作为命令的来源,会有多个源头以及源源不断的请求命令。
  • 在这些命令到达 Redis Server 以后并不是直接写入 AOF 文件,会将其这些命令先放入 AOF 缓存中进行保存。这里的 AOF 缓冲区实际上是内存中的一片区域,存在的目的是当这些命令达到一定量以后再写入磁盘,避免频繁的磁盘 IO 操作。
  • AOF 缓冲会根据 AOF 缓冲区同步文件的三种写回策略将命令写入磁盘上的 AOF 文件。
  • 随着写入 AOF 内容的增加为避免文件膨胀,会根据规则进行命令的合并(又称 AOF重写),从而起到 AOF 文件压缩的目的。
  • 当 Redis Server 服务器重启的时候会从 AOF 文件载入数据。

AOF 缓冲区三种写回策略

  • always:同步写回,每个写命令执行完立刻同步地将日志写回磁盘;
  • everysec:每秒写回,每个写命令执行完,只是先把日志写到 AOF 文件的内存缓冲区,每隔 1 秒把缓冲区中的内容写入磁盘;
  • no:操作系统控制的写回,每个写命令执行完,只是先把日志写到 AOF 文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘。
配置项写回时机优点缺点
Always同步写回可靠性搞,数据基本不丢失每个写命令都要落盘,性能影响较大
Everysec每秒写回性能适中宕机时丢失 1 秒内的数据
No操作系统控制的写回性能好宕机时丢失数据较多

操作

配置文件说明

开启 AOF

配置文件设置 appendonly yes ,默认是 no 关闭,设置为 yes 就打开 aof 持久化支持。

使用默认写回策略,每秒钟

# appendfsync always
appendfsync everysec
# appendfsync no

AOF 文件——保存路径

Redis 6

AOF 保存文件的位置喝 RDB 保存文件的位置一样,都是通过 redis.conf 配置文件的 dir 位置

# Note that you must specify a directory here, not a file name.

dir /path

# rdb file storage path: /path/dump.rdb
# aof file storage path: /path/appendonly.aof
Redis 7
# For convenience. Redis stores all persistent append-only files in a dedicated directory. The name of the directory is determined by the appenddirname configuration parameter.

dir /path
appenddirname "appendonlydir"

# rdb file storage path: /path/dump.rdb
# aof file storage path: /path/appendonlydir/xxx.aof

AOF 文件——保存名称

Redis 6

有且仅有一个

# The name of the append only file (default: "appendonly.aof")
appendfilename "appendonly.aof"
Redis 7 Multi Part AOF 的设计

和 Redis 6 相比,从 1 个文件变成 3 个文件。

顾名思义,MP-AOF 就是将原来的单个 AOF 文件拆分成多个 AOF 文件。在 MP-AOF 中,我们将 AOF 分为三种类型(base 基本文件,incr 增量文件和 manifest 清单文件),分别为:

  • BASE:表示基础 AOF,它一般由子进程通过重写产生,该文件最多只有一个。
  • INCR:表示增量 AOF,它一般会在 AOFRW 开始执行时被创建,该文件可能存在多个。
  • HISTORY:表示历史 AOF,它有 BASE 和 INCR AOF 变化而来,每次 AOFRW 成功完成时,本地 AOFRW 之前对应的 BASE 和 INCR AOF 都将变为 HISTORY,HISTORY 类型的 AOF 会被 Redis 自动删除。

为了管理这些 AOF 文件,我们引入一个 manifest(清单)文件来跟踪、管理这些 AOF。同时,为了便于 AOF 备份和拷贝,我们将所有的 AOF 文件和 manifest 文件放入一个单独的文件目录中,目录名由 appenddirname 配置(Redis 7.0 新增配置项)决定。

# 几种类型文件的前缀,后跟有关序列和类型的附加信息
appendfilename "appendonly.aof"

# 新版本增加的目录配置项目
appenddirname "appendonlydir"

# 如有下的 aof 文件存在
base
  appendonly.aof.1.base.rdb
incr
  appendonly.aof.1.incr.aof
  appendonly.aof.2.incr.aof
manifest
  appendonly.aof.manifest

正常恢复

  • 启动:设置 Yes ,修改默认的 appendonly no 改为 yes
  • 写操作继续,生成 aof 文件到指定目录
  • 恢复 1:重启 redis 然后重新加载,结果 OK
  • 恢复 2
    • 写入数据进 redis,然后 flushdb + shutdown 服务器
    • 新生成了 dump 和 aof
    • 备份新生成的 aof.bak,然后删除 dump/aof 再看恢复
    • 重启 redis 然后重新加载
    • 停止服务器,我们的备份修改后在重新启动服务器

异常恢复

  • 故意乱写正常的 AOF 文件;模拟网络闪断文件写 error
  • 重启 Redis 之后就会进行 AOF 文件的载入,报错无法启动
  • 异常修复命令,redis-check-aof --fix [file] 进行修复
  • 重启服务

优势

更好的保护数据不丢失、性能高、可做紧急恢复。

  • 使用 AOF Redis 更加持久,可以有不同的 fsync 策略:根本不 fsync、每秒 fsync、每次查询时 fsync。使用每秒 fsync 的默认策略,写入性能仍然很棒。fsync 是使用后台线程执行的,当没有 fsync 正在进行时,主线程将努力执行写入,因此您只能丢失一秒钟的写入。
  • AOF 日志是一个仅附加日志,因此不会出现寻道问题,也不会在断电时出现损坏问题。即使由于某种原因(磁盘已满或其他原因)日志以写一半的命令结尾,redis-check-aof 工具也能够轻松修复它。
  • 当 AOF 变得太大时,Redis 能够在后台自动重写 AOF。重写是完全安全的,因为当 Redis 继续附加到旧文件时,会使用创建当前数据集所需的最少操作集生成一个全新的文件,一旦第二个文件准备就绪,Redis 就会切换两者并开始附加到新的那一个。
  • AOF 以易于理解和解析的格式依次包含所有操作的日志。您甚至可以轻松导出 AOF 文件。例如,即使您不小心使用该 FLUSHALL 命令刷新了所有内容,只要在此期间没有执行日志重写,您仍然可以通过停止服务器、删除最新命令并重新启动 Redis 来保存您的数据集。

劣势

相同的数据集的数据,aof 文件要远大于 rdb 文件,恢复速度慢于 rdb;

aof 运行效率要慢于 rdb,每秒同步策略效率较好,不同步效率和 rdb 相同。

  • AOF 文件通常比相同数据集的等效 RDB 文件大。
  • 根据确切的 fsync 策略,AOF 可能比 RDB 慢。一般来说,将 fsync 设置为每秒性能仍然非常高,并且在禁用 fsync 的情况下,即使在高负载下它也应该与 RDB 一样快。即使在巨大的写入负载的情况下,RDB 仍然能够提供关于最大延迟的更多保证。

AOF 重写机制

概述

由于 AOF 持久化是 Redis 不断将写命令记录到 AOF 文件中,随着 Redis 不断的进行,AOF 的文件会越来越大,文件越大,占用服务器内存越大以及 AOF 恢复要求时间越长。

为了解决这个问题,Redis 新增了重写机制,当 AOF 文件的大小超过所设定的峰值时,Redis 就会自动启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集或者可以手动使用命令 bgrewriteaof 来重新。

触发机制

  • 官网默认配置

    auto-aof-rewrite-percentage 100
    auto-aof-rewrite-min-size 64mb
    
    # 注意,同时满足,且的关系才会触发
    # 1.根据上次重写后的 aof 大小,判断当前 aof 大小是不是增长了 1 倍
    # 2.重写时满足的文件大小
  • 自动触发

    满足配置文件中的选项后,Redis 会记录上次重写时的 AOF 大小,默认配置是当 AOF 文件大小是上次 rewrite 后大小的一倍且文件大小 64M 时。

  • 手动触发

    客户端向服务器发送 bgrewriteaof 命令。

案例说明

  • 需求说明

    启动 AOF 文件的内容压缩,只保留可以恢复数据的最小指令集。例如

    set k1 v1
    set k1 v2
    set k1 v3

    如果不重写,那么这 3 条语句都在 aof 文件中,内容占空间不说启动的时候都要执行一遍,共计 3 条命令;但我们实际只需要 set k1 v3 这一条。所以开启重写后,只需要保存 set k1 v3 最后一次修改值,相当于给 aof 文件瘦身减肥,性能更好。AOF 重写不仅降低了文件的占用空间,同时更小的 AOF 也可以更快地被 Redis 加载。

  • 启动 AOF 文件的内容压缩,只保留可以恢复数据的最小指令集。

  • 操作

    • 配置准备

      • 修改配置文件,开启 aof

        appendonly yes
      • 重写峰值修改为 1k

        auto-aof-rewrite-min-size 1k
      • 关闭混合,默认 yes,修改为 no

        aof-use-rdb-preamble no
      • 删除之前的全部 aof 和 rdb,清除干扰项

    • 自动触发案例

      • 重启 redis 服务,执行 set k1 v1 查看 aof 文件是否正常;
      • 查看 aof 三类配置文件;
      • k1 不停的重写 value,使 appendonly.aof.1.incr.aof 暴涨;
      • 重写触发,appendonly.aof.1.incr.aof 文件自动瘦身后将内容存放到 appendonly.aof.2.base.aof ,删除 appendonly.aof.1.incr.aof ,生成新的 0KB 的 appendonly.aof.2.incr.aof 文件。
    • 手动触发案例

      客户端向服务器发送 bgrewriteaof 命令

  • 结论

    AOF 文件重写并不是对源文件进行重新整理,而是直接读取服务器现有的键值对,然后用一条命令去代替之前记录这个键值对的多条命令,生成一个新的文件后去替换原来的 AOF 文件。

    AOF 文件重写触发机制:通过 redis.conf 配置文件中的 auto-aof-rewrite-percentage 默认值为 100,以及 auto-aof-rewrite-min-size 64mb 配置,也就是默认 Redis 会记录上次重写时的 AOF 大小,默认配置时当 AOF 文件大小是上次 rewrite 后大小的一倍且文件大于 64M 时触发

重写原理

  • 在重写开始前,Redis 会创建一个重写子进程,这个子进程会读取现有的 AOF 文件,并将其包含的指令进行分析压缩并写入到一个临时文件中;
  • 与此同时,主进程会将新接收到的写指令一边累积到内存缓冲区中,一边继续写入到原有的 AOF 文件中,这样做是保证原有的 AOF 文件的可用性,避免在重写过程中出现意外;
  • 重写子进程完成重写工作后,它会给父进程发一个信号,父进程收到信号后就会将内存中缓存的写指令追加到新 AOF 文件中;
  • 当追加结束后,Redis 就会用新 AOF 文件来代替旧 AOF 文件,之后再有新的写指令,就都会追加到新的 AOF 文件中;
  • 重写 AOF 文件的操作,并没有读取旧的 AOF 文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的 AOF 文件,这点和快照有点类似。

AOF 优化配置项详解

配置文件 APPEND_ONLY_MODE 模块

配置指令配置含义配置示例
appendonly是否开启 aofappendonly yes
appendfilename文件名称appendfilename "appendonly.aof"
appendfsync同步方式everysec/always/no
no-appendfsync-on-rewriteaof 重写期间是否同步no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage
auto-aof-rewrite-min-size
重写触发配置、文件重写策略auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

总结

  • 优点
    • AOF 文件是一个只进行追加的日志文件;
    • Redis 可以在 AOF 文件体积变得过大时,自动在后台对 AOF 进行重写;
    • AOF 文件有序地保存了对数据库执行的所有写入操作,这些写入操作以 Redis 协议的格式保存,因此 AOF 文件的内容非常容易被人读懂,对文件进行分析也很轻松。
  • 缺点
    • 对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积;
    • 根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB。