append only file

以独立日志的方式记录每次写命令, 重启时再重新执行 AOF 文件中的命令达到恢复数据的目的。AOF 的主要作用
是解决了数据持久化的实时性, 目前已经是 Redis 持久化的主流方式。

5.2.1 使用 AOF

  • 开启 AOF: appendonly yes, 默认不开启
  • 文件名: appendfilename 配置, 默认 appendonly.aof
  • 保存路径: 配置方法和 RDB 一样

AOF 工作流程:

image.png

  • rewrite 用于压缩

5.2.2 命令写入

文本协议格式:

  1. *3\r\n$3\r\nset\r\n$5\r\nhello\r\n$5\r\nworld\r\n

为什么采用文本协议?

  • 文本协议具有很好的兼容性
  • 开启 AOF 后, 所有写入命令都包含追加操作, 直接采用 (文本?) 协议格式, 避免了二次处理开销 (编解码?)
  • 文本协议具有可读性, 方便直接修改和处理

为什么把命令追加到 aof_buf 中?

  • 避免性能完全取决于磁盘
  • 提供多种缓冲区同步硬盘策略, 在性能和安全性方面做出平衡

5.2.3 文件同步

同步策略由 appendfsync 控制:

image.png

系统调用 write 和 fsync 说明:

  1. write 操作会触发延迟写 (delayed write) 机制。Linux 在内核提供页缓冲区用来提高硬盘IO性能。write 操作在写入系统缓冲区后直接返回。同步硬盘操作依赖于系统调度机制, 例如: 缓冲区页空间写满或达到特定时间周期。同步文件之前, 如果此时系统故障宕机, 缓冲区内数据将丢失。
  2. fsync 针对单个文件操作 (比如 AOF 文件), 做强制硬盘同步, fsync 将阻塞直到写入硬盘完成后返回, 保证了数据持久化。
  3. 配置为 always 时, 每次写入都要同步 AOF 文件, 在一般的 SATA 硬盘上, Redis 只能支持大约几百 TPS 写入, 显然跟 Redis 高性能特性背道而驰, 不建议配置。
  4. 配置为 no, 由于操作系统每次同步 AOF 文件的周期不可控, 而且会加大每次同步硬盘的数据量, 虽然提升了性能, 但数据安全性无法保证。
  5. 配置为 everysec, 是建议的同步策略, 也是默认配置, 做到兼顾性能和数据安全性。理论上只有在系统突然宕机的情况下丢失1秒的数据。(严格来说最多丢失1秒数据是不准确的, 5.3节会做具体介绍到。)

5.2.4 重写机制

压缩文件体积

AOF 文件重写是把 Redis 进程内的数据转化为写命令同步到新 AOF 文件的过程.

重写后的AOF文件为什么可以变小?

  • 进程内已经超时的数据不再写入文件
  • 旧的 AOF 文件含有无效命令, 如 del key1、hdel key2、srem keys、set a111、set a222 等。重写使用进程内数据直接生成, 这样新的AOF文件只保留最终数据的写入命令
  • 多条写命令可以合并为一个, 如: lpush list a、lpush list b、lpush list c可以转化为: lpush list a b c。为了防止单条命令过大造成客户端缓冲区溢出, 对于 list、set、hash、zset 等类型操作, 以64个元素为界拆分为多条

更小的 AOF 文件可以更快地被 Redis 加载

AOF重写过程可以手动触发和自动触发:

  • 手动触发: 直接调用 bgrewriteaof 命令
  • 自动触发: 根据 auto-aof-rewrite-min-size 和 auto-aof-rewrite-percentage 参数确定自动触发时机
    • auto-aof-rewrite-min-size: 表示运行 AOF 重写时文件最小体积, 默认为 64MB
    • auto-aof-rewrite-percentage: 代表当前 AOF 文件空间 (aof_current_size) 和上一次重写后 AOF 文件空间 (aof_base_size) 的比值
    • 自动触发时机 = aof_current_size > auto-aof-rewrite-min-size && (aof_current_size-aof_base_size)/aof_base_size >= auto-aof-rewrite-percentage

image.png

  • aof_rewrite_buf: 保存 fork 过程中新接收的命令
  • 4) 每次批量写入硬盘数据量由配置 aof-rewrite-incremental-fsync 控制, 默认为 32MB, 防止单次刷盘数据过多造成硬盘阻塞

5.2.5 重启加载

服务器重启时的数据恢复:

image.png
图5-4 Redis 持久化文件加载流程

5.2.6 文件校验

加载损坏的 AOF 文件时会拒绝启动

对于错误格式的 AOF 文件, 先进行备份, 然后采用 redis-check-aof—fix 命令进行修复, 修复后使用 diff -u 对比数据的差异, 找出丢失的数据,有些可以人工修改补全

AOF 文件可能存在结尾不完整的情况, 比如机器突然掉电导致 AOF 尾部文件命令写入不全。Redis 为我们提供了 aof-load-truncated 配置来兼容这种情况,默认开启。加载 AOF 时, 当遇到此问题时会忽略并继续启动, 同时打印如下警告日志:

image.png