深入Redis的RDB和AOF两种持久化方式以及AOF重写机制的分析

深入Redis的RDB和AOF两种持久化方式以及AOF重写机制的分析

在Redis的高可用架构中,持久化是保障数据不丢失的核心机制。Redis提供了RDB和AOF两种持久化方案,它们分别以「快照」和「日志」的思路实现数据落盘,同时AOF还通过重写机制解决了日志膨胀问题。本文将系统拆解这两种持久化方式的原理、流程与优劣,并结合流程图帮助你彻底理解。


一、RDB持久化:内存快照的备份方案

1.1 什么是RDB?

RDB(Redis Database)可以理解为内存快照:在指定时刻将Redis内存中的全量数据生成二进制快照,并写入磁盘。

你可以把Redis想象成一个水杯,向Redis写入数据就像往杯子里倒水;而RDB持久化就像用相机给这个水杯拍一张照片,拍照的这一瞬间 ,照片里记录的水杯水量,就是当前Redis的数据快照

T1时刻:Redis有10个key,生成快照1;T2时刻:Redis有20个key,生成快照2

1.2 RDB触发机制

RDB持久化分为手动触发自动触发两种方式,自动触发本质上也是调用手动命令。

手动触发
  • SAVE命令 :同步执行,会阻塞Redis主进程直到RDB完成,大数据量下会导致长时间不可用,线上环境禁止使用
  • BGSAVE命令 :后台执行,Redis主进程会fork一个子进程来完成RDB生成,主进程仅在fork阶段短暂阻塞,是线上推荐的手动方式。
自动触发

redis.conf中通过save <seconds> <changes>配置规则:

conf 复制代码
save 900 1    # 900秒内有1次写操作则触发BGSAVE
save 300 10   # 300秒内有10次写操作则触发BGSAVE
save 60 10000 # 60秒内有10000次写操作则触发BGSAVE

此外,执行SHUTDOWN命令且未开启AOF时,Redis会自动执行一次BGSAVE

1.3 RDB执行流程



执行BGSAVE
是否有持久化任务执行?
直接返回
主进程fork子进程
子进程生成临时RDB文件
子进程完成后通知主进程
主进程用临时文件替换旧RDB文件
RDB持久化完成

流程细节

  1. 主进程检查是否有RDB/AOF任务在执行,若有则直接返回。
  2. fork子进程时会短暂阻塞主进程,完成后主进程恢复读写。
  3. 子进程基于主进程内存生成临时快照文件,期间主进程的写操作会写入临时内存副本,待子进程完成后再同步到主内存。
  4. Redis默认使用LZF算法压缩RDB文件,大幅减少磁盘占用。

1.4 RDB优缺点

优点 缺点
RDB文件紧凑,体积小,适合定时备份与灾难恢复 无法做到实时持久化,fork子进程是重量级操作,会阻塞主进程
Redis加载RDB速度远快于AOF,直接恢复内存数据 宕机时会丢失上一次BGSAVE到宕机间的所有数据
老版本Redis可能不兼容新版本RDB格式

二、AOF持久化:日志回放的实时方案

2.1 什么是AOF?

AOF(Append Only File)以日志形式 记录每一条写命令,服务重启时通过重放AOF文件中的命令来恢复内存数据。它解决了RDB的实时性问题,是目前Redis持久化的主流方案。

最朴素的思路是:Redis每执行一次写操作,除了写内存,同时也写一份到磁盘,但这样会严重影响性能------因为磁盘IO远慢于内存。

优化方案:主线程只负责写内存并返回结果,另起后台线程异步写磁盘,避免阻塞主进程。

2.2 开启AOF

AOF默认关闭,需在redis.conf中配置开启:

conf 复制代码
appendonly yes    # 开启AOF
appendfilename "appendonly.aof" # AOF文件名

2.3 AOF执行流程

ALWAYS
EVERYSEC
NO
客户端写命令
主线程写内存
返回客户端结果
命令追加到aof_buf缓冲区
根据fsync策略刷盘
每次写操作后刷盘
每秒刷盘
由操作系统决定刷盘时机

核心优化点 :写命令先写入aof_buf缓冲区,再通过不同fsync策略同步到磁盘,平衡性能与安全性。

三种fsync策略对比
策略 含义 优点 缺点
AOF_FSYNC_ALWAYS 每次写操作后立即刷盘 数据安全性最高,理论上最多丢失1次操作 性能最差,每个写操作都会阻塞主进程
AOF_FSYNC_EVERYSEC 每秒刷盘一次(默认) 兼顾性能与安全性,性能接近无持久化 宕机时最多丢失1秒数据
AOF_FSYNC_NO 不主动刷盘,由OS调度 性能最好 数据安全性最低,宕机时丢失数据不可控

线上推荐使用默认的EVERYSEC策略,在性能和数据安全之间取得最佳平衡。

2.4 AOF重写机制:解决日志膨胀

随着业务运行,AOF文件会越来越大,不仅占用磁盘空间,还会拖慢数据恢复速度。为此Redis引入了AOF重写机制,通过压缩日志来瘦身。

重写原理

AOF重写不是基于旧文件修改,而是遍历当前内存数据,生成最小化的命令集合

  • 同一个key的多次写入,只保留最后一次赋值命令
  • 已删除/过期的key,不再记录任何写命令
  • 批量命令合并(如LPUSH多次操作合并为一次)
重写触发机制
  • 手动触发 :执行BGREWRITEAOF命令直接触发AOF重写。

  • 自动触发 :在redis.conf中配置阈值:

    conf 复制代码
    auto-aof-rewrite-min-size 64mb       # AOF文件最小重写大小
    auto-aof-rewrite-percentage 100      # 当前AOF比上次重写后大100%时触发

    即:AOF文件≥64MB,且比上次重写后的文件大100%时,自动执行BGREWRITEAOF

2.5 AOF重写流程

有AOF重写
有RDB任务

执行BGREWRITEAOF
是否有AOF重写/ RDB任务?
直接返回
等待RDB完成后执行
主进程fork子进程
子进程遍历内存生成临时AOF文件
主进程将重写期间写命令写入AOF重写缓冲区
子进程完成后通知主进程
主进程将重写缓冲区数据写入AOF缓冲区
用临时AOF文件替换旧AOF文件
AOF重写完成

关键细节

  1. 重写期间主进程的写操作会写入AOF重写缓冲区,避免数据丢失。
  2. 子进程重写时不影响原有AOF写入流程,保证服务可用性。
  3. 重写过程中,主进程仅在fork、刷写重写缓冲区、替换文件三个阶段短暂阻塞。

三、Redis重启时的文件加载顺序

Redis重启时会优先加载AOF文件,因为AOF数据实时性更高;如果AOF文件不存在,才会尝试加载RDB文件;若两者都不存在,则直接启动空实例。




Redis重启
AOF文件存在?
加载AOF文件并回放命令
RDB文件存在?
加载RDB文件恢复内存
直接启动空实例
启动完成

注意:加载AOF或RDB文件时若发生错误,Redis会启动失败并打印错误日志。


四、RDB vs AOF:如何选择?

维度 RDB AOF
数据实时性 低,可能丢失快照间数据 高,最多丢失1秒数据(默认配置)
恢复速度 快,直接加载二进制数据 慢,需要重放所有命令
文件体积 小(压缩后) 大(日志形式),需重写压缩
性能影响 fork子进程时短暂阻塞 后台异步刷盘,阻塞极小
适用场景 数据备份、灾难恢复、对实时性要求不高的业务 对数据实时性要求高的核心业务

最佳实践

  • 核心业务 :开启AOF,使用默认AOF_FSYNC_EVERYSEC策略,保证数据安全与性能。
  • 备份场景 :配合RDB定时备份,每天执行BGSAVE生成快照,用于跨机房灾备。
  • 混合持久化 (Redis 4.0+):开启aof-use-rdb-preamble yes,AOF重写时先写RDB快照,再追加增量日志,兼顾RDB恢复快和AOF实时性的优点。

五、总结

  • RDB:以快照形式备份全量数据,恢复快、体积小,但实时性差,适合备份与灾备。
  • AOF:以日志形式记录写命令,实时性高、数据安全,是线上主流方案,但需通过重写机制解决日志膨胀。
  • AOF重写:通过遍历内存生成最小化命令集,压缩AOF文件,保证服务长期稳定运行。
  • 加载顺序:Redis重启时优先加载AOF,再加载RDB,保障数据尽可能完整。

理解这两种持久化机制的底层原理,才能在实际业务中根据数据安全、性能要求做出最优选择,避免因持久化配置不当导致数据丢失或服务性能下降。

相关推荐
jgyzl2 小时前
2026.3.12 常见的缓存读写策略
java·后端·spring
培小新2 小时前
MySQL 集群技术(环境+一主二从配置)
数据库·mysql
ruanyongjing2 小时前
Spring TransactionTemplate 深入解析与高级用法
java·数据库·spring
fengxin_rou2 小时前
[Redis从零到精通|第六篇]:Redis的主从同步
java·数据库·redis·缓存
zhglhy2 小时前
Java系统限流方法技术优劣
java·限流
java干货2 小时前
拒绝全表扫描灾难:用 SSCAN 安全遍历 Redis 亿级 Set 集合
数据库·redis·安全
xiaoye37082 小时前
Spring Bean 生命周期
java·spring
刘一说2 小时前
使用 CLion 搭建 Redis 6.x 源码调试环境:从零开始的完整指南
数据库·redis·缓存
6+h2 小时前
【Spring】Bean的生命周期详解
java·python·spring