Redis 持久化

一、支持的持久化模式

1. RDB(Redis Database,默认开启)

(1)原理

按指定策略生成内存数据的二进制快照文件(dump.rdb)。

(2)优点

恢复速度快、文件体积小、对性能影响低。

(3)缺点

数据一致性弱(可能丢失最近写入数据)。

2. AOF(Append Only File,默认关闭)

(1)原理

记录所有写命令到日志文件(appendonly.aof),重启时重放命令恢复数据。

(2)优点

数据一致性高(可配置秒级 / 实时刷盘)。

(3)缺点

文件体积大、恢复速度慢、写性能略降。

3. 混合持久化(8.4 优化)

(1)原理

RDB + AOF 结合:AOF 文件前半部分为 RDB 快照,后半部分为增量 AOF 命令。

(2)优点

兼顾 RDB 恢复速度和 AOF 数据一致性。

(3)缺点

文件结构稍复杂,需兼容新旧版本解析。

4. 纯缓存模式

(1)原理

同时关闭 RDB 和 AOF。

二、RDB 持久化

1. 定义

Redis 按「触发条件」将内存中所有数据以二进制格式一次性写入 dump.rdb 文件,重启时加载该文件恢复数据。8.4 优化了 RDB 生成时的内存拷贝策略(Copy-on-Write 机制),减少主线程阻塞。

2. 原理

(1)示意图

image

3. 常用操作

(1)SAVE

同步生成 RDB 快照(主线程阻塞,禁止生产使用),复杂度为 O(N)(N 为总键数)。

(2)BGSAVE

异步生成 RDB 快照(fork 子进程执行,主进程不阻塞),复杂度为主进程 O(1) / 子进程 O(N)(N 为总键数)。

(3)LASTSAVE

获取最后一次 RDB 快照生成的时间戳(UNIX 时间),复杂度为 O(1)。
时间戳转日期:date -d @1766977049

(4)CONFIG REWRITE

将当前 RDB 配置写入 redis.conf(替代手动修改配置文件),复杂度为 O(1)。

4. 核心配置

(1)save

RDB 自动触发条件(如 save 900 1 表示 900 秒内至少 1 个键修改则触发)。
动态配置:

config set save ""  

(2)dbfilename

RDB 文件名。

(3)dir

RDB/AOF 文件存储目录。

(4)rdbcompression

是否压缩 RDB 文件(LZF 算法)。

(5)rdbchecksum

RDB 文件写入后是否校验 CRC64 校验和(防文件损坏)。

(6)stop-writes-on-bgsave-error

BGSAVE 失败时是否停止写操作(防止数据不一致)。

5. 触发条件

(1)自动触发

满足 save 配置的时间 + 修改次数条件(如 60 秒内 10000 次修改)。

(2)手动触发

执行 SAVE/BGSAVE 命令。

(3)特殊触发

  • 主从复制时主节点触发 BGSAVE 生成 RDB 发送给从节点;
  • 执行 FLUSHALL/FLUSHDB 时(若开启 RDB)生成空 RDB;
  • Redis 正常关闭(SHUTDOWN)时触发 BGSAVE。

6. 检查和修复

[root@yingzai conf]#redis-check-rdb dump.rdb   
[offset 0] Checking RDB file dump.rdb  
[offset 26] AUX FIELD redis-ver = '8.4.0'  
[offset 40] AUX FIELD redis-bits = '64'  
[offset 52] AUX FIELD ctime = '1766976689'  
[offset 67] AUX FIELD used-mem = '843264'  
[offset 79] AUX FIELD aof-base = '0'  
[offset 81] Selecting DB ID 0  
[offset 128] Checksum OK  
[offset 128] \o/ RDB looks OK! \o/  
[info] 5 keys read  
[info] 0 expires  
[info] 0 already expired  
[info] 0 subexpires  

7. 业务场景

  • 数据备份:每日凌晨执行 BGSAVE 生成 RDB 快照,归档到备份服务器;
  • 主从复制:主节点通过 RDB 向从节点同步全量数据(增量用 AOF);
  • 灾难恢复:数据丢失时快速加载 RDB 恢复核心数据(适合对数据一致性要求不高的场景,如缓存);
  • 低性能损耗场景:对写性能要求高、可接受少量数据丢失(如商品缓存,丢失 5 分钟内数据可接受)。

8. 注意事项

  • 禁止生产环境使用 SAVE:同步生成 RDB 会阻塞主线程,导致 Redis 无法响应请求,甚至触发超时;
  • BGSAVE 依赖 fork 子进程:fork 时会拷贝主进程页表,内存越大 fork 耗时越长(8.4 优化了大内存下的 fork 效率),可通过 INFO stats 查看 latest_fork_usec 监控 fork 耗时;
  • RDB 压缩会消耗 CPU:若 Redis 服务器 CPU 紧张,可关闭 rdbcompression(trade-off:文件体积变大);
  • 自动触发的 save 条件不宜过严:如设置 save 1 1(1 秒 1 次修改就触发)会频繁 fork 子进程,导致性能下降;
  • RDB 文件不可编辑:二进制格式仅能通过 Redis 加载,无法手动修改。

三、AOF 持久化

1. 定义

将所有写命令(如 SET、HSET、ZADD)以文本协议格式追加到 appendonly.aof 文件,Redis 重启时通过重放 AOF 文件中的命令恢复数据。8.4 优化了 AOF 重写的内存占用和命令合并逻辑(如将多个 INCR 合并为 SET)。

2. 原理

(1)示意图

image

3. 常用操作

(1)CONFIG SET appendonly yes

开启 AOF 持久化(需重启或执行 BGREWRITEAOF 生效),复杂度为 O(1)。

(2)BGREWRITEAOF

异步重写 AOF 文件(压缩命令,如合并多次修改为单次),复杂度为主进程 O(1) / 子进程 O(N)(N 为总键数)。

(3)REWRITEAOF

早期版本的同步阻塞重写命令(已废弃,Redis 2.8+ 后不再推荐 / 文档化)(阻塞主线程,禁止生产使用),复杂度为 O(N)(N 为总键数)。

(4)CONFIG SET appendfsync

修改 AOF 刷盘策略,复杂度为 O(1)。

4. 核心配置

(1)appendonly

是否开启 AOF 持久化。

(2)appendfilename

AOF 文件名。
Redis 7 之后,aof 文件拆分成了 3 个:

[root@yingzai conf]#tree appendonlydir/  
appendonlydir/  
├── appendonly.aof.1.base.rdb  
├── appendonly.aof.1.incr.aof  
└── appendonly.aof.manifest  
  • base:基础文件,一般由子进程重写产生,只有一个;
  • incr:增量文件,在重写开始时被创建,可能有多个;
  • history:历史文件,每次重写成功后,使用的 base 和 incr 文件都会变成 history,此文件会被 Redis 自动删除;
  • manifest:清单文件,用于跟踪、管理以上文件。

(3)appendfsync

AOF 刷盘策略,三种写回策略:

  • always:实时刷盘,数据最安全;
  • everysec:每秒刷盘,平衡性能与安全(默认);
  • no:交给操作系统刷盘。

(4)auto-aof-rewrite-percentage

AOF 重写触发百分比(当前 AOF 文件比上次重写后大 N% 则触发),默认 100(即增大 1 倍触发)。

(5)auto-aof-rewrite-min-size

AOF 重写最小文件大小(避免小文件频繁重写),默认 64mb。

(6)aof-use-rdb-preamble

开启混合持久化(AOF 文件前半部分为 RDB 快照),8.4 默认开启。
单独测试 aof 机制时,要关闭混合持久化,排除干扰。

(7)aof-load-truncated

AOF 文件尾部损坏时,是否忽略损坏部分继续加载,默认 yes。

5. 核心流程

(1)示意图

image

(2)命令追加

所有写命令先写入 AOF 缓冲区(aof_buf)。

(3)刷盘策略

按 appendfsync 配置将缓冲区数据刷到磁盘。

(4)文件重写

当 AOF 文件达到重写条件时,BGREWRITEAOF 生成「精简版 AOF 文件」(如将 INCR page:view 1 100 次合并为 SET page:view 100),替换旧文件。

(5)数据恢复

Redis 重启时,优先加载 AOF 文件(若开启),重放所有命令恢复数据。

6. 检查和修复

(1)正常恢复

(2)异常恢复

# aof incr 尾端添加无效字符  
[root@yingzai appendonlydir]#cat appendonly.aof.1.incr.aof   
*2  
$6  
SELECT  
$1  
0  
*5  
$4  
mset  
$2  
k1  
$2  
v1  
$2  
k2  
$2  
v2  
sdfasdfasdfafds  
# 此时可能正常启动,但是这个文件是损坏的,需要修复  
# 修复时,截掉了尾端格式错乱的部分  
[root@yingzai appendonlydir]#redis-check-aof --fix appendonly.aof.1.incr.aof   
Start checking Old-Style AOF  
AOF appendonly.aof.1.incr.aof format error  
AOF analyzed: filename=appendonly.aof.1.incr.aof, size=86, ok_up_to=69, ok_up_to_line=17, diff=17  
This will shrink the AOF appendonly.aof.1.incr.aof from 86 bytes, with 17 bytes, to 69 bytes  
Continue? [y/N]: y  
Successfully truncated AOF appendonly.aof.1.incr.aof  
[root@yingzai appendonlydir]#cat appendonly.aof.1.incr.aof   
*2  
$6  
SELECT  
$1  
0  
*5  
$4  
mset  
$2  
k1  
$2  
v1  
$2  
k2  
$2  
v2  

7. 重写机制

(1)核心目的

解决 AOF 日志文件 “越写越大” 的问题:AOF 会记录所有写命令(比如多次 INCR),长期运行文件体积膨胀,重写就是生成精简版 AOF 文件(把冗余命令合并、无效命令删除),缩小体积、加速重启恢复。

(2)触发方式

  • 自动触发(两个条件同时满足):
    • AOF 文件大小 ≥ auto-aof-rewrite-min-size(默认 64MB);
    • 文件比上次重写后增大 ≥ auto-aof-rewrite-percentage(默认 100%,即翻倍)。
  • 手动触发:执行 BGREWRITEAOF(推荐);禁止用 REWRITEAOF(同步重写,阻塞主线程)。

(3)核心原理

  • 无阻塞执行:主进程 fork 子进程处理重写(用 Copy-on-Write 机制,子进程读内存、主进程正常处理写命令);
  • 命令精简:子进程不遍历旧 AOF,直接基于当前内存数据生成 “最终态命令”(比如 10 次 INCR key 1 合并为 SET key 10,删除过期 / 无用命令);
  • 混合持久化(默认开启):8.4 生成的新 AOF 文件,前半部分是 RDB 二进制快照(加载快),后半是增量 AOF 命令(保一致性);
  • 缓存追加:重写期间,主线程新接收的写命令会暂存到 “重写缓冲区”,子进程写完后,主线程把缓冲区命令追加到新 AOF,最后替换旧文件。

8. 业务场景

  • 高数据一致性场景:金融交易、订单数据(需保证秒级内数据不丢失,配置 appendfsync everysec);
  • 核心业务缓存:用户会话、支付状态(不允许丢失最近写入数据);
  • 混合持久化场景:开启 aof-use-rdb-preamble,兼顾 RDB 恢复速度和 AOF 数据一致性(8.4 主推模式)。

9. 注意事项

  • appendfsync always 性能损耗大:每次写命令都刷盘,Redis 写 QPS 会大幅下降(建议仅在极致数据安全场景使用);
  • AOF 重写会 fork 子进程:与 BGSAVE 一样,大内存下 fork 耗时需监控,避免与 BGSAVE 同时触发(8.4 会自动规避同时 fork);
  • AOF 文件损坏处理:若 AOF 文件尾部损坏,可通过 redis-check-aof --fix appendonly.aof 修复;若损坏严重,可切换到 RDB 恢复;
  • 混合持久化兼容问题:8.4 生成的混合 AOF 文件,低版本 Redis(<5.0)无法加载,需注意版本兼容;
  • AOF 命令重放耗时:超大 AOF 文件(如几十 GB)恢复时,重放命令耗时久,建议结合混合持久化或分库存储。

四、混合持久化

1. 定义

8.4 默认开启的持久化模式(aof-use-rdb-preamble yes),AOF 文件由两部分组成:

  • 前半部分:RDB 二进制快照(全量数据,体积小、加载快);
  • 后半部分:增量 AOF 命令(RDB 生成后新增的写命令,保证数据一致性)。

2. 数据恢复和加载流程

(1)优先加载 AOF 文件

image

3. 注意事项

  • 需保证 RDB 和 AOF 配置均合理:如 RDB 自动触发策略、AOF 刷盘策略;
  • 混合 AOF 文件备份:需完整备份,拆分 RDB 和 AOF 部分会导致无法加载;
  • 升级 / 回滚:升级 Redis 版本前需备份混合 AOF 文件,避免新版本解析异常。

五、面试题

1. Redis RDB 和 AOF 的区别?如何选型?

(1)对比

image

(2)选型原则

  • 纯缓存场景(如商品列表):仅开启 RDB(兼顾性能,丢失少量数据可接受);
  • 核心业务(如订单、支付):开启混合持久化(RDB+AOF),兼顾速度与一致性;
  • 极致数据安全(如金融交易):AOF + appendfsync everysec(避免 always 性能损耗);
  • 主从集群:主节点开启混合持久化,从节点仅加载数据(可关闭持久化节省磁盘)。

2. BGSAVE/BGREWRITEAOF 的实现原理?为什么不会阻塞主线程?

(1)核心依赖

Linux 的 Copy-on-Write(写时复制)机制:

  • 执行 BGSAVE/BGREWRITEAOF 时,Redis 主线程 fork 一个子进程,子进程共享主线程的内存页表;
  • 子进程遍历内存生成 RDB/AOF 文件,期间主线程可正常处理写命令;
  • 若主线程修改某块内存数据,会复制该内存页(写时复制),子进程仍读取旧数据,不影响快照 / 重写;
  • 子进程完成后,通知主线程,生成新的 RDB/AOF 文件。

(2)「不阻塞主线程」的关键

fork 后子进程独立执行落盘操作,主进程仅在 fork 瞬间(拷贝页表)短暂阻塞。

3. Redis 重启时,加载 RDB 和 AOF 的优先级?混合持久化如何加载?

(1)优先级

AOF 文件(若开启且存在)> RDB 文件 > 空数据库。

(2)混合持久化加载流程

  • 先加载 AOF 文件中的 RDB 部分(二进制快照),快速恢复全量数据;
  • 再加载 AOF 文件中的增量命令部分,重放新增写命令;
  • 若 RDB 部分损坏,尝试加载纯 AOF 部分;若 AOF 部分损坏,按 aof-load-truncated 配置处理(忽略损坏部分或报错)。

4. 如何优化 Redis 持久化的性能?

(1)RDB 优化

  • 禁用 SAVE,仅用 BGSAVE;
  • 调整 save 触发策略(如放宽为 3600 1 300 100),减少 fork 频率;
  • CPU 紧张时关闭 rdbcompression,以空间换时间。

(2)AOF 优化

  • 配置 appendfsync everysec(平衡性能与一致性),避免 always;
  • 调高 auto-aof-rewrite-percentage(如 200),减少重写频率;
  • 开启混合持久化(aof-use-rdb-preamble yes)。

(3)通用优化

  • 保证 Redis 服务器有足够内存,减少 fork 时的内存拷贝;
  • 将持久化文件存储到高速磁盘(如 SSD);
  • 避免 BGSAVE 和 BGREWRITEAOF 同时触发(8.4 自动规避,低版本需手动控制);
  • 主从集群中,仅主节点开启持久化,从节点关闭(从节点通过主节点同步数据)。

5. Redis 持久化文件损坏如何处理?

(1)RDB 文件损坏

  • 用 redis-check-rdb dump.rdb 检查损坏位置;
  • 若损坏轻微,工具可自动修复;若严重,恢复最近的备份 RDB 文件;
  • 无备份时,切换到 AOF 文件恢复(若开启)。

(2)AOF 文件损坏

  • 用 redis-check-aof --fix appendonly.aof 修复(工具会删除损坏的命令);
  • 修复后仍无法加载,关闭 AOF,加载 RDB 文件,再重新开启 AOF。

(3)预防措施

  • 开启 rdbchecksum/AOF 校验,检测文件损坏;
  • 定期备份持久化文件到独立服务器;
  • 避免服务器异常断电(配置 UPS 或开启磁盘缓存刷盘策略)。

6. 为什么 Redis 不推荐同时开启高频率 RDB 和 AOF?

  • 性能损耗:高频率 RDB(如 save 1 1)会频繁 fork 子进程,叠加 AOF 刷盘 / 重写,导致 CPU / 内存压力过大;
  • 磁盘 IO 竞争:RDB 和 AOF 同时落盘会抢占磁盘 IO,导致写延迟升高;
  • 数据冗余:混合持久化已兼顾两者优势,无需单独开启高频率 RDB;
  • 优化方案:保留 RDB 每日备份的低频触发(如 save 86400 1),AOF 开启混合模式,兼顾备份和实时一致性。