难度:⭐⭐⭐⭐ | 适合人群:想掌握Redis持久化的开发者
💥 开场:一次"灾难性"的数据丢失
时间: 周五晚上11点
地点: 家里(刚准备睡觉)
事件: 紧急故障电话
运维(电话里): "Redis服务器重启了,所有缓存数据都丢了!"
我: "什么???" 😱(一个激灵坐起来)
运维: "现在数据库压力巨大,快撑不住了!"
我: "Redis不是会持久化吗?怎么会丢数据?" 😰
紧急连上服务器查看配置:
# redis.conf
save "" # ← 持久化被禁用了!
appendonly no # ← AOF也关闭了!
我: "卧槽!谁把持久化关了???" 😱
运维: "上次性能优化,有人说持久化影响性能,就关了..."
我: "......" 😭
第二天早上,紧急会议:
技术总监: "这次事故给大家敲响警钟,Redis持久化必须配置好!"
哈吉米: "Redis有两种持久化方式:RDB和AOF。"
南北绿豆: "不同场景选择不同方式,不能一刀切。"
阿西噶阿西: "我给大家讲讲这两种方式的原理和选择..."
🎯 第一问:为什么需要持久化?
Redis的特点
哈吉米: "先回顾一下Redis的特点。"
Redis = 内存数据库
↓
优点:
- 读写速度快(微秒级)
- 性能高
缺点:
- 数据存在内存中
- 服务器重启 → 数据全丢失
- 断电 → 数据全丢失
持久化的作用
南北绿豆: "持久化就是把内存中的数据保存到磁盘。"
持久化的目的:
1. 数据备份
- 防止数据丢失
2. 故障恢复
- 重启后恢复数据
3. 数据迁移
- 从一台机器迁移到另一台
💾 第二问:RDB(快照)持久化
什么是RDB?
RDB = Redis Database(快照文件)
阿西噶阿西: "RDB就是把某一时刻的所有数据拍个'快照',保存成文件。"
类比:
RDB持久化 = 给数据库拍照
每隔一段时间拍一张照片
↓
保存成dump.rdb文件
↓
需要恢复时,读取照片
RDB工作原理
1. Redis fork一个子进程
↓
2. 子进程将数据写入临时RDB文件
↓
3. 写入完成后,替换旧的RDB文件
↓
4. 父进程继续处理客户端请求(不阻塞)
关键技术: fork + 写时复制(Copy-On-Write)
触发RDB的三种方式
方式1:手动触发 - SAVE命令
redis> SAVE
OK
特点:
- ✅ 立即执行
- ❌ 阻塞Redis服务(慎用)
- ❌ 生产环境禁用
流程:
执行SAVE
↓
Redis主进程暂停处理请求
↓
创建RDB文件
↓
完成后继续处理请求
方式2:手动触发 - BGSAVE命令
redis> BGSAVE
Background saving started
特点:
- ✅ 后台执行
- ✅ 不阻塞Redis服务
- ✅ 生产环境推荐
流程:
执行BGSAVE
↓
fork子进程
↓
子进程创建RDB文件
↓
主进程继续处理请求(不阻塞)
方式3:自动触发 - 配置规则
redis.conf配置:
# 900秒内至少有1个key被修改
save 900 1
# 300秒内至少有10个key被修改
save 300 10
# 60秒内至少有10000个key被修改
save 60 10000
满足任一条件就触发BGSAVE
哈吉米: "还有其他自动触发场景:"
1. 执行shutdown命令
2. 执行flushall命令
3. 主从复制时(全量复制)
RDB文件
文件位置:
# 查看配置
redis> CONFIG GET dir
1) "dir"
2) "/var/lib/redis"
redis> CONFIG GET dbfilename
1) "dbfilename"
2) "dump.rdb"
# 完整路径:/var/lib/redis/dump.rdb
文件内容(二进制):
REDIS0009 # Redis版本号
...
# 数据库选择
selectdb 0
...
# Key-Value数据
string key1 value1
hash key2 field1 value1 field2 value2
...
# 校验和
checksum
RDB的优缺点
南北绿豆: "RDB优缺点很明显。"
优点:
✅ 文件紧凑,适合备份
✅ 恢复速度快(直接加载到内存)
✅ 性能好(fork子进程,不影响主进程)
✅ 适合大规模数据恢复
缺点:
❌ 数据可能丢失(两次快照间隔的数据)
❌ fork子进程耗时(数据量大时)
❌ 不适合实时持久化
场景演示:
10:00:00 - 执行BGSAVE,保存快照
10:05:00 - 写入1000条新数据
10:10:00 - Redis宕机
↓
丢失10:00-10:10之间的数据(1000条)
📝 第三问:AOF(追加文件)持久化
什么是AOF?
AOF = Append Only File(只追加文件)
阿西噶阿西: "AOF记录每一个写命令,像是Redis的'日志'。"
类比:
RDB = 拍照(每隔一段时间拍一张)
AOF = 录像(记录每一个动作)
AOF工作原理
1. 客户端执行写命令
↓
2. Redis将命令追加到AOF缓冲区
↓
3. 根据策略同步到AOF文件
↓
4. AOF文件会定期重写(压缩)
示例:
# 执行命令
SET name "张三"
SET age "25"
DEL name
HSET user:1 name "李四"
# AOF文件内容(文本格式)
*3
$3
SET
$4
name
$6
张三
*3
$3
SET
$3
age
$2
25
*2
$3
DEL
$4
name
*4
$4
HSET
$6
user:1
$4
name
$6
李四
AOF配置
启用AOF:
# redis.conf
appendonly yes # 开启AOF
# AOF文件名
appendfilename "appendonly.aof"
# AOF同步策略
appendfsync everysec # 每秒同步(推荐)
# appendfsync always # 每次写入都同步(最安全但慢)
# appendfsync no # 由操作系统决定(最快但不安全)
三种同步策略
哈吉米: "AOF有三种同步策略,各有优劣。"
策略1:always(总是同步)
执行写命令
↓
写入AOF缓冲区
↓
立即调用fsync同步到磁盘 ← 每次都同步
↓
返回客户端
特点:
- ✅ 数据最安全(最多丢失1个命令)
- ❌ 性能最差(每次都写磁盘)
- ❌ 磁盘IO频繁
策略2:everysec(每秒同步,推荐)
执行写命令
↓
写入AOF缓冲区
↓
返回客户端
↓
后台线程每秒调用fsync同步 ← 每秒同步
特点:
- ✅ 性能好
- ✅ 数据安全性高(最多丢失1秒数据)
- ✅ 平衡了性能和安全
- ✅ 生产环境推荐
策略3:no(不主动同步)
执行写命令
↓
写入AOF缓冲区
↓
返回客户端
↓
由操作系统决定何时同步 ← 不管了
特点:
- ✅ 性能最好
- ❌ 数据不安全(可能丢失大量数据)
- ❌ 不推荐
三种策略对比
| 策略 | 性能 | 安全性 | 丢失数据 | 推荐度 |
|---|---|---|---|---|
| always | 慢 🐢 | 最安全 ✅ | 最多1条命令 | ⭐⭐ |
| everysec | 快 ⚡ | 安全 ✅ | 最多1秒数据 | ⭐⭐⭐⭐⭐ |
| no | 最快 ⚡⚡ | 不安全 ❌ | 可能几分钟 | ⭐ |
南北绿豆: "99%的场景用everysec就够了!"
AOF重写机制
问题: AOF文件会越来越大!
SET name "张三"
SET name "李四"
SET name "王五"
SET name "赵六"
# AOF记录了4条命令
但实际上只需要:
SET name "赵六" # 只需要最后一条
AOF重写:
重写前AOF文件(100条命令):
SET k1 v1
SET k1 v2
SET k1 v3
...
DEL k2
SET k2 v4
...
重写后AOF文件(10条命令):
SET k1 v3 # 只保留最终状态
SET k2 v4
...
文件大小: 从100MB → 10MB
触发重写:
# 手动触发
redis> BGREWRITEAOF
Background append only file rewriting started
# 自动触发(配置)
auto-aof-rewrite-percentage 100 # 文件大小增长100%时重写
auto-aof-rewrite-min-size 64mb # 文件至少64MB才重写
重写流程:
1. fork子进程
↓
2. 子进程遍历内存数据,生成新AOF文件
↓
3. 主进程继续处理请求,新命令写入:
├─ 旧AOF文件
└─ AOF重写缓冲区
↓
4. 子进程完成,通知主进程
↓
5. 主进程将重写缓冲区的命令追加到新AOF
↓
6. 用新AOF替换旧AOF
📊 第四问:RDB vs AOF全方位对比
对比表格
| 维度 | RDB | AOF |
|---|---|---|
| 持久化方式 | 快照(数据) | 日志(命令) |
| 文件大小 | 小(紧凑) | 大(记录所有命令) |
| 恢复速度 | 快 ⚡ | 慢 🐢 |
| 数据完整性 | 差(可能丢失几分钟) | 好(最多丢失1秒) |
| 性能影响 | 小 | 稍大 |
| 适用场景 | 备份、容灾 | 数据安全性要求高 |
| 推荐度 | ⭐⭐⭐ | ⭐⭐⭐⭐ |
详细对比
文件大小对比
RDB:
数据量:1000万条
RDB文件:500MB(紧凑的二进制)
AOF:
数据量:1000万条
AOF文件:2GB(文本格式的命令)
重写后:1GB(压缩了冗余命令)
恢复速度对比
测试场景: 1GB数据恢复
RDB恢复:
加载dump.rdb
↓
直接读取到内存
↓
完成!
↓
耗时:5-10秒
AOF恢复:
加载appendonly.aof
↓
逐条执行每个命令
↓
完成!
↓
耗时:30-60秒
结论: RDB恢复速度快5-10倍!
数据丢失对比
场景: 10:00:00执行持久化,10:05:00宕机
RDB(配置save 300 1):
10:00:00 - 保存快照
10:01:00 - 写入1000条数据
10:02:00 - 写入1000条数据
10:03:00 - 写入1000条数据
10:04:00 - 写入1000条数据
10:05:00 - Redis宕机
↓
丢失:10:00-10:05之间的4000条数据 ❌
AOF(appendfsync everysec):
10:00:00 - 同步到AOF
10:00:01 - 同步到AOF
...
10:04:59 - 同步到AOF
10:05:00 - Redis宕机(最后1秒没同步)
↓
丢失:最后1秒的数据(约10-100条)✅
🔀 第五问:混合持久化(Redis 4.0+)
什么是混合持久化?
南北绿豆: "Redis 4.0引入了混合持久化,结合RDB和AOF的优点!"
原理:
混合持久化 = RDB快照 + AOF增量日志
AOF重写时:
├─ 前半部分:RDB格式(数据快照)
└─ 后半部分:AOF格式(增量命令)
配置
# redis.conf
aof-use-rdb-preamble yes # 开启混合持久化
混合持久化文件
appendonly.aof文件内容:
REDIS0009 ← RDB格式头
[RDB格式的数据快照]
...
REDIS ← AOF格式开始
*3
$3
SET
$4
name
$6
张三
...
优势
阿西噶阿西: "混合持久化的优势:"
✅ 恢复速度快(RDB格式加载快)
✅ 数据完整性好(AOF增量补充)
✅ 文件相对小(RDB紧凑)
✅ 兼顾性能和安全
对比:
| 方式 | 恢复速度 | 数据丢失 | 推荐度 |
|---|---|---|---|
| 纯RDB | 最快 ⚡⚡ | 较多 ❌ | ⭐⭐⭐ |
| 纯AOF | 慢 🐢 | 最少 ✅ | ⭐⭐⭐⭐ |
| 混合 | 快 ⚡ | 少 ✅ | ⭐⭐⭐⭐⭐ |
🛠️ 第六问:生产环境配置建议
场景1:数据安全性要求高
示例: 金融系统、支付系统
推荐配置:
# 启用AOF
appendonly yes
appendfsync everysec
# 启用混合持久化
aof-use-rdb-preamble yes
# RDB作为辅助
save 900 1
save 300 10
save 60 10000
# AOF重写配置
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
理由:
- AOF保证数据安全(最多丢1秒)
- RDB作为备份(快速恢复)
- 混合持久化兼顾性能
场景2:性能要求高,允许少量数据丢失
示例: 缓存系统、Session存储
推荐配置:
# 只用RDB
save 900 1
save 300 10
save 60 10000
# 关闭AOF
appendonly no
理由:
- 性能最好
- 缓存数据可以重建
- 丢失几分钟数据可接受
场景3:高性能 + 高安全(推荐)
示例: 大部分生产环境
推荐配置:
# 启用混合持久化
appendonly yes
appendfsync everysec
aof-use-rdb-preamble yes
# RDB配置相对宽松
save 3600 1 # 1小时内有1次修改
save 300 100 # 5分钟内有100次修改
save 60 10000 # 1分钟内有10000次修改
# AOF重写
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# 优化配置
no-appendfsync-on-rewrite yes # 重写时不同步(避免阻塞)
💻 第七问:实战演示
演示1:RDB持久化
1. 配置Redis:
# redis.conf
save 10 1 # 10秒内有1次修改就保存(测试用)
dir /data/redis
dbfilename dump.rdb
2. 写入数据:
redis> SET user:1 "张三"
OK
redis> SET user:2 "李四"
OK
redis> SET user:3 "王五"
OK
# 查看最后保存时间
redis> LASTSAVE
(integer) 1705824000
# 等待10秒...
# 再次查看
redis> LASTSAVE
(integer) 1705824010 # 时间变了,说明保存了
3. 模拟宕机:
# 强制杀掉Redis进程
kill -9 <redis-pid>
# 重启Redis
redis-server /etc/redis/redis.conf
# 检查数据
redis> GET user:1
"张三" # 数据恢复了!
redis> GET user:2
"李四"
redis> GET user:3
"王五"
演示2:AOF持久化
1. 配置Redis:
# redis.conf
appendonly yes
appendfsync everysec
appendfilename "appendonly.aof"
2. 写入数据:
redis> SET name "张三"
OK
redis> SET age "25"
OK
redis> HSET user:1 name "李四" age "30"
OK
3. 查看AOF文件:
cat /data/redis/appendonly.aof
# 输出(简化版):
*3
$3
SET
$4
name
$6
张三
*3
$3
SET
$3
age
$2
25
...
4. 模拟宕机恢复:
# 杀掉Redis
kill -9 <redis-pid>
# 重启Redis(会自动加载AOF)
redis-server /etc/redis/redis.conf
# 检查数据
redis> GET name
"张三"
redis> GET age
"25"
redis> HGETALL user:1
1) "name"
2) "李四"
3) "age"
4) "30"
演示3:AOF损坏修复
场景: AOF文件损坏(写入一半时宕机)
修复工具:
# Redis提供了修复工具
redis-check-aof --fix appendonly.aof
# 输出:
AOF analyzed, error found, recovered 1234 commands
AOF file fixed
然后重启Redis即可
🎯 第八问:持久化性能优化
优化1:fork优化
哈吉米: "fork子进程耗时主要取决于内存大小。"
# 优化内存分配
vm.overcommit_memory = 1
# 禁用透明大页
echo never > /sys/kernel/mm/transparent_hugepage/enabled
优化2:磁盘优化
# 使用SSD硬盘
# 避免和其他IO密集应用共享磁盘
# 调整文件系统参数(ext4、xfs)
优化3:重写优化
# AOF重写时不同步(避免阻塞)
no-appendfsync-on-rewrite yes
# 重写缓冲区大小
aof-rewrite-incremental-fsync yes
优化4:监控指标
监控这些指标:
# RDB相关
redis> INFO persistence
rdb_last_save_time:1705824010 # 最后保存时间
rdb_last_bgsave_status:ok # 最后保存状态
rdb_last_bgsave_time_sec:5 # 最后保存耗时
rdb_current_bgsave_time_sec:-1 # 当前保存耗时(-1表示未在进行)
# AOF相关
aof_enabled:1 # AOF是否启用
aof_rewrite_in_progress:0 # 是否在重写
aof_last_rewrite_time_sec:10 # 最后重写耗时
aof_current_size:104857600 # 当前AOF文件大小
aof_base_size:52428800 # 上次重写后的大小
💡 知识点总结
持久化核心要点
✅ 两种持久化方式
- RDB:快照,定期保存
- AOF:日志,记录命令
✅ RDB特点
- 文件小、恢复快
- 可能丢失数据
- 适合备份
✅ AOF特点
- 数据完整性好
- 文件大、恢复慢
- 适合数据安全性要求高的场景
✅ AOF三种同步策略
- always:最安全,最慢
- everysec:推荐,平衡性能和安全
- no:最快,不安全
✅ 混合持久化
- Redis 4.0+支持
- 结合RDB和AOF优点
- 生产环境推荐
✅ 生产配置
- 高安全:AOF(everysec) + RDB
- 高性能:只用RDB
- 推荐:混合持久化
记忆口诀
RDB快照像拍照,
定期保存数据好。
文件小来恢复快,
可能丢失要知道。
AOF日志记命令,
每秒同步最稳健。
数据安全有保障,
文件大来恢复慢。
混合持久两结合,
快照加上增量补。
生产环境推荐用,
性能安全都兼顾。
🤔 常见面试题
Q1: RDB和AOF的区别?
A:
RDB:
- 快照方式,保存某时刻的所有数据
- 文件小,恢复快
- 可能丢失较多数据
- 适合备份
AOF:
- 日志方式,记录所有写命令
- 文件大,恢复慢
- 数据完整性好
- 适合数据安全性要求高的场景
生产推荐:混合持久化(Redis 4.0+)
Q2: AOF的三种同步策略?
A:
1. always:每次写入都同步
- 最安全,最慢
- 最多丢失1个命令
2. everysec:每秒同步(推荐)
- 平衡性能和安全
- 最多丢失1秒数据
3. no:不主动同步
- 最快,不安全
- 可能丢失大量数据
生产环境99%用everysec
Q3: AOF为什么要重写?
A:
原因:
- AOF记录所有写命令,文件会越来越大
- 包含大量冗余命令(如SET同一个key多次)
重写作用:
- 去除冗余命令
- 只保留最终状态
- 文件大小从几GB压缩到几百MB
触发时机:
- 手动:BGREWRITEAOF命令
- 自动:文件大小增长100%时
Q4: 生产环境如何配置?
A:
推荐配置(混合持久化):
appendonly yes
appendfsync everysec
aof-use-rdb-preamble yes
save 3600 1
save 300 100
save 60 10000
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
no-appendfsync-on-rewrite yes
理由:
- 混合持久化兼顾性能和安全
- everysec最多丢1秒数据
- 自动重写控制文件大小
💬 写在最后
从RDB到AOF,再到混合持久化,我们全面学习了Redis的持久化机制:
- 💾 理解了两种持久化方式的原理
- 📊 掌握了各自的优缺点
- 🔀 学会了混合持久化的使用
- 🛠️ 了解了生产环境的配置建议
这篇文章,希望能让你在生产环境中正确配置Redis持久化!
如果这篇文章对你有帮助,请:
- 👍 点赞支持
- ⭐ 收藏备用
- 🔄 转发分享
- 💬 评论交流
下一篇我们聊Redis的三大经典问题:缓存穿透、击穿、雪崩! 👋