AOF 持久化原理

面试官问:"Redis 的 AOF 是什么?"

小陈说:"AOF 是 Append Only File,把所有写命令记录下来。"

面试官追问:"AOF 有几种刷盘策略?哪种最安全?"

小陈说:"...always?"

面试官继续追问:"那 always 和 everysec 有什么区别?性能差多少?"

小陈开始答不上来。

AOF 是 Redis 持久化的另一核心机制。相比 RDB 的数据快照,AOF 是操作日志,能做到更高的数据安全性。这道题能说清楚三种刷盘策略和 AOFRW 重写机制的候选人,对 Redis 持久化有系统理解。

一、AOF 持久化概述 🔴

1.1 AOF vs RDB

维度RDBAOF
原理数据快照操作日志
数据完整性可能丢数据可配置(最多丢 1 秒)
文件大小小(二进制压缩)大(文本日志)
恢复速度快(直接加载)慢(重放命令)
写入性能fork 子进程,不影响主进程每条命令都要写日志

1.2 AOF 写入流程

客户端 → 主线程执行命令 → 追加到 AOF buffer

                    AOF buffer → (刷盘策略) → AOF 文件

1.3 ❌ 错误示范

候选人原话:"AOF 每次写命令都刷盘,所以比 RDB 慢很多。"

问题诊断:AOF 有多种刷盘策略,always 每次都刷,everysec 每秒刷一次,no 由系统决定刷盘时机。只有 always 才每次都刷盘。

候选人原话 2:"AOF 比 RDB 好,所以应该只用 AOF。"

问题诊断:AOF 文件比 RDB 大,恢复比 RDB 慢。建议 RDB + AOF 混合使用,或者根据业务场景选择。

【面试官心理】 这道题我能从"为什么需要 AOF"切入。RDB 可能丢最后一次快照后的数据,AOF 通过记录操作日志解决这个问题。能说清楚这个本质区别的候选人,说明他理解了持久化的目的。

二、三种刷盘策略 🔴

2.1 刷盘策略对比

策略说明性能数据安全性
always每个写命令都 fsync 刷盘最低最高(不丢数据)
everysec每秒一次 fsync中等最多丢 1 秒数据
no不主动刷盘,由系统决定最高最多丢一个 OS 刷盘周期

2.2 各策略详解

# redis.conf
appendonly yes
appendfsync always      # 每个写命令都刷盘
# appendfsync everysec   # 每秒刷盘(默认)
# appendfsync no         # 不主动刷盘

always

// 每次写入 AOF 后立即 fsync
write(cmd, AOF_BUFFER);
fsync(fd);  // 强制写入磁盘
return;
  • QPS 影响:10,000~50,000(取决于磁盘性能)
  • SSD:影响较小
  • HDD:影响巨大(随机写入)

everysec

// 后台线程每秒执行一次 fsync
void *fsyncThread(void *arg) {
    while (1) {
        sleep(1);
        // 批量 fsync 过去 1 秒内的所有写入
        fysnc(fd);
    }
}
  • QPS 影响:几乎无影响
  • 数据安全性:最多丢失 1 秒数据
  • 推荐配置

no

// 完全依赖 OS 的刷盘策略
write(cmd, AOF_BUFFER);  // 只写到内核缓冲区
// OS 在合适时机刷盘(通常 30 秒内)
return;
  • QPS 影响:无
  • 数据安全性:取决于 OS,通常 30 秒内

三、AOFRW 重写机制 🟡

3.1 AOF 文件膨胀

-- AOF 记录的是命令,不是数据
-- INCR counter  执行 1000 次
-- AOF 文件:
-- INCR counter
-- INCR counter
-- ...
-- (1000 行)

-- RDB 存储:
-- counter = 1000
-- (1 行)

3.2 重写原理

-- AOF 重写(AOFRW):
-- 1. fork 子进程
-- 2. 子进程读取当前内存数据,重写为 SET 命令
--    读取 counter = 1000
--    写入: SET counter 1000
-- 3. 原来的 1000 行 → 1 行

-- 重写过程中,新命令仍追加到原 AOF
-- 主进程把新命令追加到 AOF buffer 和重写 buffer
-- 重写完成后,用重写 buffer 追加到新 AOF
-- rename 新 AOF,替换旧 AOF

3.3 触发方式

# 手动触发
BGREWRITEAOF

# 自动触发(根据 AOF 文件大小)
auto-aof-rewrite-percentage 100  # AOF 文件比上次重写后大 100% 时触发
auto-aof-rewrite-min-size 64mb   # AOF 文件至少 64MB 时才触发

四、混合持久化 🟡

4.1 混合持久化原理

Redis 4.0 引入混合持久化

AOF 重写时:
1. 先 fork 子进程
2. 子进程将当前数据以 RDB 格式写入 AOF 文件开头
3. 后续命令以 AOF 格式追加

结果:
┌─────────────┬─────────────────────────────────┐
│   RDB格式   │    AOF 格式(增量命令)           │
│  (二进制)   │  (文本命令)                       │
└─────────────┴─────────────────────────────────┘

4.2 配置与效果

# 开启混合持久化
aof-use-rdb-preamble yes

# 效果:
# - 恢复速度:快(直接加载 RDB 部分)
# - 数据安全:完整(AOF 部分补上增量)
# - 文件大小:比纯 AOF 小

五、生产避坑 🟡

5.1 性能调优

# 开启 AOF 缓冲
appendfsync everysec

# 开启 AOF 重写
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

# 关闭合并写
aof-rewrite-incremental-fsync yes  # 每 32MB 重写一次,避免大文件重写阻塞

5.2 AOF vs RDB 选择

-- 推荐:RDB + AOF 混合
-- RDB:定时备份(如每天凌晨 3 点)
-- AOF:实时持久化

-- 只用 AOF:
-- - 数据安全性要求极高
-- - 接受恢复速度较慢

-- 只用 RDB:
-- - 容忍少量数据丢失
-- - 追求恢复速度

【面试官心理】 AOF 持久化是 Redis 面试中的高频题。能说清楚三种刷盘策略和混合持久化的候选人,说明他对 Redis 的数据安全性设计有深入理解。


级别考察重点期望回答
P5基本概念AOF 记录写命令、RDB 是数据快照
P6刷盘策略always/everysec/no 的区别
P7深度机制AOFRW 重写原理、混合持久化