Redis持久化机制
Redis作为高性能内存数据库,数据默认存储于内存中,若服务器意外宕机,数据将全部丢失。持久化机制是Redis保障数据可靠性的核心手段,其本质是将内存数据以特定格式写入磁盘,以便重启时恢复。 Redis提供两种经典持久化方式(RDB、AOF),并在4.0+版本引入混合持久化,兼顾性能与可靠性。
# RDB:快照式持久化
RDB是Redis默认的持久化方式,核心是在指定时间点生成内存数据的全量快照,并写入磁盘文件(默认名为dump.rdb)。
# 1. RDB触发条件
RDB触发分为手动触发和自动触发,核心区别在于是否阻塞主线程。
# 手动触发
| 命令 | 执行方式 | 阻塞性 | 适用场景 |
|---|---|---|---|
| SAVE | 主线程直接执行快照 | 是 | 仅测试或紧急备份,生产环境禁用 |
| BGSAVE | fork子进程执行快照 | 否 | 生产环境手动备份(推荐) |
- SAVE风险:在主线程执行,期间Redis无法处理客户端请求,阻塞时间随数据量增长而延长(GB级数据可能阻塞秒级)。
- BGSAVE优势:通过fork子进程负责写盘,主线程继续处理请求,仅fork瞬间有短暂阻塞(微秒级)。
# 自动触发
Redis通过配置文件的save <秒数> <修改次数>规则自动触发BGSAVE,满足任一规则即执行:
# redis.conf 默认配置
save 900 1 # 900秒内至少1次修改
save 300 10 # 300秒内至少10次修改
save 60 10000 # 60秒内至少10000次修改
2
3
4
其他自动触发场景:
FLUSHALL:清空所有数据时,触发SAVE(生成空RDB文件);- 主从复制:主节点接收从节点同步请求时,自动触发BGSAVE生成快照并发送;
- 正常关闭(
SHUTDOWN):触发SAVE确保数据落盘后退出。
# 2. RDB核心原理:写时复制(Copy-On-Write)
BGSAVE的高效依赖fork子进程和写时复制机制,确保快照一致性且不阻塞主线程:
fork子进程:主线程执行
fork()时,操作系统采用写时复制策略——父子进程共享内存页表(不立即复制实际数据),子进程拥有独立空间,可安全遍历内存生成快照,主线程继续处理请求。子进程生成RDB:子进程遍历内存数据,按Redis二进制格式写入临时文件,完成后替换旧RDB文件。
写时复制生效:
- 若主线程不修改数据,父子进程共享内存页,子进程读取原始数据;
- 若主线程修改数据,操作系统复制该内存页,主线程操作新页,子进程继续读取旧页,确保快照数据是fork时刻的一致状态。
资源回收:子进程完成后通过信号通知主线程,主线程更新持久化状态(如
rdb_last_save_time)。
# 3. RDB文件结构
RDB为二进制压缩格式,结构固定,确保高效存储与校验:
+----------+----------+----------+----------+----------+
| 魔数 | 版本号 | 数据部分 | 校验和 | 结束符 |
+----------+----------+----------+----------+----------+
2
3
| 字段 | 作用 |
|---|---|
| 魔数 | "REDIS"字符串,标识为Redis RDB文件 |
| 版本号 | 无符号整数(如009表示Redis 9.0) |
| 数据部分 | 按数据库分块存储,包含键值对、过期时间等 |
| 校验和 | 无符号整数,验证文件完整性 |
| 结束符 | 固定值0xFF,标识文件结束 |
# 4. RDB加载流程
Redis启动时,若未开启AOF或AOF文件不存在,则加载RDB:
- 检查
dir配置目录下是否存在dump.rdb; - 验证魔数和校验和,确保文件未损坏;
- 按RDB结构解析数据并加载到内存;
- 加载完成后,启动事件循环处理客户端请求。
# 5. RDB优缺点
| 优点 | 缺点 |
|---|---|
| 加载速度快(二进制直接加载) | 数据丢失风险高(快照间隔内数据丢失) |
| 磁盘占用小(压缩存储) | fork开销随数据量增大(页表复制可能阻塞主线程) |
| 性能影响低(异步执行) | 不适合实时持久化(无法做到秒级零丢失) |
# AOF:命令日志式持久化
AOF(Append Only File)通过记录所有写命令实现持久化,重启时重放命令恢复数据,数据完整性远高于RDB。
# 1. AOF核心流程
AOF分为三个阶段,每个阶段可配置,平衡性能与安全性:
- 命令追加:Redis执行写命令后,将命令追加到内存AOF缓冲区(避免频繁写盘);
- 文件写入:调用
write()系统调用,将缓冲区数据写入内核缓冲区(仍未刷盘); - 磁盘刷盘:调用
fsync()/fdatasync()将内核缓冲区数据刷到磁盘,刷盘时机由appendfsync配置决定。
# 2. AOF刷盘策略
appendfsync是AOF的核心配置,直接影响数据安全性与性能:
| 配置值 | 刷盘时机 | 数据丢失风险 | 性能影响 |
|---|---|---|---|
| always | 每次命令追加后立即刷盘 | 无 | 高(IO密集) |
| everysec | 每秒异步刷盘(默认) | 最多丢失1秒数据 | 中 |
| no | 由操作系统决定(通常30秒) | 高(可能丢失分钟级数据) | 低 |
# 3. AOF重写:解决日志膨胀
AOF文件会随命令追加不断增大(如多次修改同一key会记录所有命令),导致加载慢、磁盘占用高。AOF重写是Redis优化AOF文件的核心机制,通过遍历内存数据生成精简命令集(如10次INCR key替换为SET key 10),优化文件大小。
# 触发条件
- 手动触发:执行
BGREWRITEAOF(fork子进程执行,非阻塞); - 自动触发:同时满足以下配置:
# redis.conf 配置
auto-aof-rewrite-percentage 100 # AOF文件大小增长100%触发
auto-aof-rewrite-min-size 64mb # 文件至少64MB才触发(避免小文件频繁重写)
2
3
# 重写流程
- 子进程遍历内存数据,生成精简AOF命令写入新文件;
- 主线程继续处理请求,新写命令同时追加到旧AOF缓冲区和AOF重写缓冲区;
- 子进程完成后,主线程将重写缓冲区的增量命令追加到新文件;
- 替换旧AOF文件,完成重写。
# 4. AOF加载流程
- 检查
dir目录下的appendonly.aof文件; - 验证文件完整性(若损坏,Redis会尝试修复或提示手动修复);
- 逐行解析并执行命令,恢复数据;
- 加载完成后启动事件循环。
# 5. AOF优缺点
| 优点 | 缺点 |
|---|---|
| 数据完整性高(可配置秒级/实时刷盘) | 加载速度慢(需重放所有命令) |
| 易恢复(命令日志可读,可手动修改) | 磁盘占用大(命令冗余) |
| 增量持久化(仅记录写命令) | 高频刷盘降低吞吐量 |
# 混合持久化:RDB与AOF的融合
为解决RDB数据丢失多、AOF加载慢的问题,Redis 4.0+引入混合持久化,核心是AOF重写时,先写入RDB二进制数据,再追加AOF增量命令。
# 1. 混合持久化结构
开启后,AOF文件结构为:
+----------+----------------+
| RDB 头 | AOF 增量日志 |
+----------+----------------+
2
3
加载流程:先快速加载RDB头(全量数据),再重放少量AOF增量日志(RDB之后的修改),兼顾RDB的加载速度和AOF的完整性。
# 2. 开启方式
aof-use-rdb-preamble yes # 默认为no,需手动开启
# 总结:如何选择持久化方式?
| 场景 | 推荐方案 | 核心原因 |
|---|---|---|
| 数据可靠性要求高(如金融) | AOF(appendfsync everysec) | 最多丢失1秒数据,满足高可用 |
| 性能优先(如缓存场景) | RDB | 低IO开销,加载速度快 |
| 平衡可靠性与性能 | 混合持久化 | 兼具RDB的加载速度和AOF的完整性 |
实际生产中,建议结合业务对数据安全性和性能的需求,灵活配置持久化策略,并定期备份持久化文件以应对极端故障。