Redis 持久化

Redis 持久化

八月 19, 2025 次阅读

Redis 支持 RDBAOF 两种持久化机制,持久化功能有效地避免因进程退出造成数据丢失问题,当下次重启时利用之前持久化的文件即可实现数据恢复

RDB

RDB(Redis Database)是 Redis 的默认持久化方式,它会在指定的时间间隔内将数据快照保存到磁盘上,也可以通过手动触发的方式触发

触发机制

手动触发

通过 save 指令和 bgsave 指令都可以实现手动触发快照机制,两者的区别如下:

  • save 命令:阻塞当前 Redis 服务器,直到保存操作完成,对于内存比较大的实例会造成长时间的阻塞,这种情况基本不采用该命令
  • bgsave 命令:Redis 进程会执行 fork 操作创建子进程,RDB 持久化过程由子进程负责,完成后自动结束,子进程会通知父进程执行完毕,因此该指令所产生的阻塞只发生在 fork 阶段,因此时间很短。当然,fork 指令最大的开销在于进程控制块的复制和页表的复制,这些资源的复制同样是有非常大的开销的,且在子进程复制页表后,若父进程对内存进行了写操作,会触发写时拷贝,同样会有额外的资源消耗,因此并不建议频繁使用该命令

自动触发

除了手动触发以外,Redis 运行自动触发 RDB 持久化机制,这个触发机制才是在实战中更具有价值的,触发时机如下:

是的,除了手动触发(save/bgsave),自动触发 RDB 持久化 在实际生产环境中更为关键,因为它能平衡性能和数据安全,避免依赖人工干预。以下是 Redis 自动触发 RDB 的三种核心场景及其细节:


1. 通过 save 配置自动触发(最常用)
  • 配置语法
    save <seconds> <key-changes>
    例如:save 900 1 表示 900 秒内至少 1 个 key 被修改时触发 bgsave

  • 工作原理
    Redis 周期性检查是否满足配置的条件,若满足则自动启动 bgsave(后台执行,非阻塞)。

  • 默认配置(Redis 默认的 redis.conf 片段):

    save 900 1
    save 300 10
    save 60 10000

    含义:

    • 900 秒内 1 次修改 → 触发
    • 300 秒内 10 次修改 → 触发
    • 60 秒内 10000 次修改 → 触发
      (满足任意一条即触发)
  • 注意事项

    • 生产环境需根据业务负载调整参数,避免频繁触发(如高写入场景可放宽 save 条件)。
    • 若完全禁用自动保存,需配置 save ""

2. 主节点在复制时自动触发
  • 场景:当从节点(Slave)发起 全量复制(SYNC) 时,主节点(Master)会自动执行 bgsave 生成 RDB 文件,然后传输给从节点。
  • 细节
    • 即使未配置 save 规则,复制过程也会强制触发 RDB。
    • 若主节点已有最近生成的 RDB 文件(且数据未显著变化),可能直接复用该文件(Redis 7.0+ 优化)。
  • 风险
    • 主节点内存过大时,生成 RDB 可能阻塞主进程(fork + COW 开销),影响集群稳定性。
    • 解决方案:建议在低峰期扩容从节点,或使用 repl-diskless-sync 配置(无盘复制,直接通过网络发送数据,避免落盘)。

3. 执行 shutdown 时触发
  • 行为
    当执行 shutdown 命令关闭 Redis 时,如果 AOF 未开启,Redis 会默认执行一次 save(同步阻塞式 RDB 持久化),确保数据不丢失。
  • 控制参数
    • shutdown save:强制保存 RDB(默认行为)。
    • shutdown nosave:跳过保存,直接关闭。
  • 应用场景
    在维护停机前手动执行 shutdown save,比直接杀进程更安全。

配置文件

1. RDB 文件保存路径与动态配置

  • 核心机制
    • 默认路径dir /var/lib/redis/ + dbfilename dump.rdb
      (注意:默认路径可能因安装方式或操作系统而异,例如 Docker 中常见 /data

若手动修改配置文件,需重启 Redis 使其生效。

  • 生产建议
    • 持久化配置:动态修改后需同步更新 redis.conf,避免重启失效。
    • 权限管理:确保 Redis 进程对目标目录有读写权限(否则 bgsave 会静默失败)。
    • 备份策略:将 RDB 文件保存到独立磁盘或云存储(如 AWS S3),避免单点故障。

2. RDB 文件压缩的权衡

  • 技术细节

    • 算法:LZF 压缩(低 CPU 开销,适合实时场景)。
    • 压缩比:文本型数据(如 JSON)压缩率高,二进制数据(如序列化对象)效果有限。
    • 开关控制rdbcompression yes(默认开启),禁用可减少 CPU 占用(但文件体积激增)。
  • 性能影响

    场景 开启压缩 关闭压缩
    CPU 占用 较高(尤其大数据集) 几乎为零
    磁盘 I/O 写入量减少 50%~80% 写入原始数据量
    网络传输 更快(从节点同步加速) 慢(带宽占用高)

    建议

    • 在 CPU 资源充足的场景下保持开启(尤其适合云环境或网络复制)。
    • 若 Redis 实例已 CPU 过载(如单核 80%+),可临时关闭压缩缓解压力。

3. RDB 文件校验与故障恢复

  • 损坏检测

    • Redis 启动时自动校验 RDB 文件完整性(魔数 + CRC 校验),损坏则报错:
      # Fatal error loading the DB: Invalid file format.

    • 修复工具

      redis-check-rdb dump.rdb

      该工具会报告损坏位置(如无效键值对、文件截断等),但无法直接修复

  • 容灾方案

    1. 恢复备份:从最近的正常 RDB 或 AOF 文件恢复。
    2. 重建数据:若无可用的备份,可尝试手动编辑 RDB 文件(风险极高,需十六进制工具)。
    3. 从从节点提升:如果主节点 RDB 损坏,且从节点数据完整,可故障转移至从节点。
  • 预防措施

    • 定期验证:对备份的 RDB 文件运行 redis-check-rdb
    • AOF 互补:开启 appendonly yes + aof-use-rdb-preamble(混合持久化),双重保障。

Redis RDB 持久化优缺点

✅ 优点

1. 紧凑的二进制格式
  • RDB 是一个高度压缩的二进制文件,占用空间小,非常适合:

    • 数据备份(如每小时/每天全量备份)
    • 全量复制(主从同步、灾备)
  • 示例场景:

    # 每6小时备份并上传到HDFS
    save 21600 1
    hadoop fs -put /var/lib/redis/dump.rdb /backup/redis/$(date +%Y%m%d).rdb
2. 极快的恢复速度
  • 相比 AOF 的日志重放方式,RDB 直接加载二进制数据:

    • 恢复 10GB 数据:AOF 可能需要分钟级,RDB 仅需秒级
  • 重要指标:

    redis-benchmark -n 1000000 --rdb /tmp/dump.rdb  # 测试恢复速度

❌ 缺点

1. 非实时持久化
  • 致命短板:

    • bgsave 依赖 fork() 创建子进程(重量级操作
    • 频繁执行会导致:
      • CPU 峰值(COW 机制)
      • 内存双倍占用风险
  • 典型问题:

    # 监控fork耗时(超过100ms需告警)
    redis-cli info stats | grep latest_fork_usec
2. 版本兼容性风险
  • RDB 格式随 Redis 版本演进变化:
    Redis 版本 RDB 版本 兼容性风险
    <= 5.0 v6
    6.x v7
    7.x v8
  • 升级时必须测试旧版 RDB 文件的加载情况

AOF

AOF 持久化,以独立日志的方式记录每次写命令,重启时再重新执行 AOF 文件中的命令达到恢复数据的目的。AOF 的主要作用是解决数据持久化的实时性,虽然 AOF 的使用开销比 RDB 要高,但是它提供了更高的数据安全性和更细粒度的恢复能力,且当代计算机的性能已经足以支撑 AOF 的使用

若想使用 AOF,需要在配置文件中将 appendonly设置为yes,开启 AOF 持久化功能,AOF 文件名通过 appendfilename 配置,默认是 appendonly.aof,保存目录和 RDB 是一致的,通过 dir 配置指定。AOF的工作流程如下:

AOF 工作流程

1. 命令写入(Append)

  • 所有写入命令(如 SETDEL)会先写入 AOF 缓冲区(aof_buf),而不是直接写入磁盘。
  • 目的:避免频繁磁盘 I/O 影响性能。

2. 同步到磁盘(Sync)

Redis 提供 3 种同步策略(通过 appendfsync 配置):

策略 行为 数据安全性 性能影响
always 每个命令都同步写入磁盘(fsync) 最高 最差
everysec 每秒同步一次(默认) 适中 较好
no 由操作系统决定何时写入(通常 30s 左右) 最低 最好

3. AOF 重写(Rewrite)

  • 问题:AOF 文件会不断增长(如 INCR 操作 100 次会记录 100 条命令)。
  • 解决方案:Redis 会定期执行 AOF 重写(BGREWRITEAOF),生成一个更紧凑的新 AOF 文件(只保留最终状态)。
  • 触发方式
    • 手动触发:BGREWRITEAOF 命令。
    • 自动触发:通过 auto-aof-rewrite-percentageauto-aof-rewrite-min-size 配置。

4. 数据恢复(Load)

  • Redis 重启时,会优先加载 AOF 文件(如果存在)来恢复数据。
  • 执行方式:逐条执行 AOF 文件中的命令(类似于回放日志)。

AOF 流程图(Mermaid)

flowchart TD
    A[客户端写入命令] --> B[写入 AOF 缓冲区 aof_buf]
    B --> C{appendfsync 策略}
    C -->|always| D[立即同步到磁盘]
    C -->|everysec| E[每秒同步一次]
    C -->|no| F[由 OS 决定同步]
    D & E & F --> G[AOF 文件增长]
    G --> H{AOF 文件过大?}
    H -->|是| I[触发 BGREWRITEAOF]
    H -->|否| G
    I --> J[生成新 AOF 文件(压缩版)]
    J --> K[替换旧 AOF 文件]
    L[Redis 重启] --> M[加载 AOF 文件恢复数据]

AOF 重写机制

  • 触发条件
    • AOF 文件大小超过 auto-aof-rewrite-min-size
    • AOF 文件增长超过 auto-aof-rewrite-percentage

当 AOF 文件达到重写条件中的任意一个时,Redis 会自动触发 AOF 重写,生成一个新的 AOF 文件(只保留最终状态)。

流程图如下:

rewrite

  1. 执⾏ AOF 重写请求。
    如果当前进程正在执⾏ AOF 重写,请求不执行。如果当前进程正在执行 bgsave 操作,重写命令延迟到 bgsave 完成之后再执⾏。
  2. 父进程执行 fork 创建子进程。
  3. 重写
    a. 主进程 fork 之后,继续响应其他命令。所有修改操作写入 AOF 缓冲区并根据 appendfsync 策略同步到硬盘,保证旧 AOF 文件机制正确。
    b. 子进程只有 fork 之前的所有内存信息,父进程中需要将 fork 之后这段时间的修改操作写⼊ AOF 重写缓冲区中。
  4. 子进程根据内存快照,将命令合并到新的 AOF ⽂件中。
  5. 子进程完成重写
    a. 新文件写入后,子进程发送信号给⽗进程。
    b. 父进程把 AOF重写缓冲区内临时保存的命令追加到新 AOF 文件中。
    c. ⽤新 AOF 文件替换旧 AOF 文件。

Redis 启动时,会根据 RDBAOF 文件的内容,进行数据恢复:

recover

AOF 优缺点

✅ 优点

  1. 数据更安全:最多丢失 1s 数据(appendfsync everysec)。
  2. 可读性强:AOF 是文本格式(可手动编辑修复)。
  3. 自动重写:避免文件无限增长。

❌ 缺点

  1. 文件体积大:相比 RDB,AOF 文件通常更大。
  2. 恢复速度慢:需要逐条执行命令。
  3. 写入性能略低:频繁同步会影响吞吐量。

Redis 混合持久化详解

混合持久化是 Redis 4.0 引入的重要特性,它结合了 RDB 和 AOF 两种持久化方式的优点,既保证了数据安全性,又提高了恢复速度。下面我将从工作原理、实现机制、优缺点和使用建议等方面进行全面讲解。

1. 基本概念

混合持久化(RDB-AOF Hybrid Persistence)是指:

  • 在 AOF 重写时,将当前数据集以 RDB 格式写入 AOF 文件开头
  • 后续的写命令继续以 AOF 格式追加到文件中
  • 最终生成的文件前半部分是 RDB 二进制数据,后半部分是 AOF 命令文本

2. 核心实现机制

触发条件:

  1. 需要同时满足:
    • 开启了 AOF(appendonly yes)
    • 开启了混合模式(aof-use-rdb-preamble yes)
    • 触发 AOF 重写(自动或手动)

工作流程:

flowchart TD
    A[触发AOF重写] --> B[fork子进程]
    B --> C[子进程将内存数据写成RDB格式]
    C --> D[写入到新AOF文件头部]
    D --> E[父进程继续接收命令]
    E --> F[新命令以AOF格式追加到缓冲区]
    F --> G[重写完成后合并到新AOF文件]
    G --> H[替换旧AOF文件]

关键点:

  • 重写过程是非阻塞的(BGREWRITEAOF)
  • 使用写时复制(COW)机制保证数据一致性
  • 重写期间的新命令会写入两个缓冲区:
    • aof_buf:正常的AOF缓冲区
    • aof_rewrite_buf:专为重写准备的缓冲区

3. 文件结构示例

[RDB二进制数据]  ← 文件开头是RDB格式的快照
*3\r\n$3\r\nSET\r\n$5\r\nkey1\r\n$7\r\nvalue1\r\n  ← 后面追加AOF格式命令
*3\r\n$3\r\nSET\r\n$5\r\nkey2\r\n$7\r\nvalue2\r\n

4. 数据恢复过程

  1. Redis 重启时检测到 AOF 文件
  2. 发现文件开头是 RDB 魔数”REDIS”
  3. 先快速加载 RDB 部分(二进制解析)
  4. 然后按顺序执行后面的 AOF 命令
  5. 完成数据恢复

5. 配置参数

appendonly yes                  # 启用AOF
aof-use-rdb-preamble yes        # 启用混合持久化
aof-rewrite-incremental-fsync yes # 重写时增量fsync
auto-aof-rewrite-percentage 100 # 文件增长比例阈值
auto-aof-rewrite-min-size 64mb  # 最小重写大小

6. 优缺点分析

优势:

  • 恢复速度快:RDB 二进制加载比 AOF 命令回放快很多
  • 数据更安全:AOF 部分保证了重写期间的数据不丢失
  • 文件更紧凑:RDB 格式比纯 AOF 更节省空间
  • 兼容性好:支持旧版 RDB 文件格式

劣势:

  • 实现复杂度高
  • 需要 Redis 4.0+ 版本支持
  • 文件可读性降低(部分二进制)

7. 生产环境建议

  1. 对于关键业务,强烈建议开启:

    appendonly yes
    aof-use-rdb-preamble yes
    appendfsync everysec
  2. 监控重写过程:

    redis-cli info persistence | grep aof_rewrite
  3. 定期检查 AOF 文件完整性:

    redis-check-aof --fix appendonly.aof
  4. 配合适当的备份策略(如每小时备份到远程存储)

8. 性能对比

指标 纯RDB 纯AOF 混合模式
启动恢复速度
数据安全性
文件大小 中等
写入性能影响

Redis 混合持久化在 7.0 版本后的改动

在 Redis 7.0+ 的 Multi-Part AOF (MP-AOF) 持久化机制中,appendonly.aof.manifestappendonly.aof.1.base.rdbappendonly.aof.1.incr.aof 这三个文件共同协作,实现高效的数据持久化和恢复。以下是它们的详细作用和运作机制:


1. appendonly.aof.manifest(清单文件)

作用

  • 记录所有 基本文件(base)增量文件(incr) 的加载顺序,确保 Redis 重启时能正确恢复数据。
  • 类似于一个“目录”,告诉 Redis 应该按什么顺序加载数据文件。

文件内容示例

{
  "seq": 1,
  "base": [{"type": "b", "seq": 1, "file": "appendonly.aof.1.base.rdb"}],
  "incr": [{"type": "i", "seq": 1, "file": "appendonly.aof.1.incr.aof"}]
}

运作机制

  • Redis 启动时,先读取 manifest,然后按 baseincr 的顺序加载文件。
  • AOF 重写(BGREWRITEAOF 时,会生成新的 base 文件并更新 manifest,确保原子性切换。

2. appendonly.aof.1.base.rdb(基本文件)

作用

  • 存储 全量数据快照,采用 RDB 二进制格式(默认情况下,aof-use-rdb-preamble yes)。
  • 相当于传统混合持久化中的 RDB 头部,但现在是独立文件。

运作机制

  • AOF 重写 时,Redis 会 fork 子进程,将当前内存数据 序列化为 RDB 格式 并写入该文件。
  • 由于 RDB 是压缩的二进制格式,恢复速度极快(相比纯 AOF 重放命令)。

3. appendonly.aof.1.incr.aof(增量文件)

作用

  • 记录 AOF 重写之后的所有写操作,采用 Redis 协议文本格式(RESP)。
  • 类似于传统 AOF 的尾部,但现在是独立文件。

文件内容示例(RESP 协议):

*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n

运作机制

  • Redis 主进程 在执行写操作时,会同时写入:
    1. 旧 AOF 文件(如果尚未完成重写)。
    2. aof_rewrite_buf 缓冲区(用于新 incr.aof 文件)。
  • AOF 重写完成 后,增量命令会追加到 incr.aof,并更新 manifest

三者的协作流程

  1. AOF 重写触发(手动 BGREWRITEAOF 或自动触发):

    • 子进程生成新的 base.rdb(全量快照)。
    • 主进程继续接收命令,写入 incr.aof
    • 完成后,更新 manifest 指向新文件。
  2. Redis 重启恢复

    • 读取 manifest,按顺序加载:
      1. base.rdb(快速恢复全量数据)。
      2. incr.aof(重放增量命令,保证数据最新)。
  3. 文件轮转

    • incr.aof 过大时,会触发新的 AOF 重写,生成新的 base.rdbincr.aof,并更新 manifest

与传统混合持久化的区别

特性 传统混合模式(单文件) MP-AOF(多文件)
存储方式 RDB头部 + AOF尾部 base.rdb + incr.aof
文件管理 单文件,重写时替换 多文件,manifest 管理版本
恢复速度 快(RDB优先) 更快(并行加载可能)
运维友好性 难拆分备份 可单独备份 base/incr

Redis 官方推荐

  • 默认开启 MP-AOF(Redis 7.0+),因为它:
    • 健壮(文件损坏时影响更小)。
    • 高效base.rdb 加载快,incr.aof 增量小)。
  • 可通过 redis-check-aof --fix 修复损坏的 AOF 文件。

如果需要回退到传统单文件模式,可设置:

aof-use-rdb-preamble yes
aof-manifest-enabled no

但官方建议保持 MP-AOF,除非有特殊兼容性需求。