02 持久化:RDB 与 AOF
数据在内存里,断电就没了。Redis 靠两种持久化机制把数据写到硬盘:RDB(快照)和 AOF(日志)。 这是核心机制篇最重要的一章,也是面试必考题。
1. 先建立直觉:两种思路
想象你在写一份文档,防止电脑崩溃丢失内容有两种办法:
- RDB 思路:每隔一段时间"另存为"一次完整副本。崩溃后打开最近的副本——恢复快,但最后几分钟写的内容丢了。
- AOF 思路:每敲一个字都记到流水账里。崩溃后按流水账从头"重放"一遍——几乎不丢内容,但流水账很长,重放慢。
2. RDB(Redis Database):快照
是什么
RDB 把某一时刻内存中的全部数据生成一个二进制快照文件(默认叫 dump.rdb)保存到磁盘。
怎么触发
自动触发——配置文件里的 save 规则(Redis 7 的默认值):
save 3600 1 # 3600 秒内至少 1 个 key 变化,就做快照
save 300 100 # 300 秒内至少 100 个 key 变化
save 60 10000 # 60 秒内至少 10000 个 key 变化
手动触发:
127.0.0.1:6379> bgsave # 后台异步生成快照(推荐)
Background saving started
127.0.0.1:6379> save # 前台同步生成,会阻塞所有请求(生产禁用!)
bgsave 为什么不阻塞?——fork 与写时复制
bgsave 时,Redis 会 fork 出一个子进程去写快照文件,父进程继续处理请求。子进程通过操作系统的"写时复制(Copy-On-Write)"机制看到 fork 那一瞬间的数据视图,所以快照是一致的。这是面试常问点,新手记住结论即可:bgsave 由子进程完成,主进程几乎不受影响。
优缺点
| 优点 | 缺点 |
|---|---|
| 文件紧凑,适合备份、灾难恢复 | 两次快照之间的数据会丢失 |
| 恢复速度快(直接加载二进制) | fork 大内存实例时有短暂开销 |
3. AOF(Append Only File):写命令日志
是什么
AOF 把每一条写命令追加记录到日志文件。重启时把日志里的命令从头执行一遍,数据就恢复了。
默认关闭,需要手动开启:
appendonly yes
刷盘策略:appendfsync(重点)
命令先写到内存缓冲区,什么时候真正落到磁盘?三种策略:
| 策略 | 行为 | 数据安全性 | 性能 |
|---|---|---|---|
always | 每条命令都立刻刷盘 | 最多丢 1 条命令 | 慢 |
everysec(默认 ⭐) | 每秒刷一次盘 | 最多丢 1 秒数据 | 快 |
no | 交给操作系统决定(约 30 秒) | 可能丢较多 | 最快 |
默认的 everysec 是绝大多数场景的最佳平衡:性能几乎无损,最坏丢 1 秒数据。
AOF 重写(rewrite)
流水账会越来越长:对同一个 key set 了 100 次,日志里就有 100 条,其实只有最后一条有用。
AOF 重写就是"整理流水账":Redis fork 子进程,根据当前内存数据直接生成一份等价的最简命令集,替换旧日志。
127.0.0.1:6379> bgrewriteaof # 手动触发重写
自动触发条件(默认配置):
auto-aof-rewrite-percentage 100 # 文件比上次重写后大了 100%
auto-aof-rewrite-min-size 64mb # 且至少达到 64MB
优缺点
| 优点 | 缺点 |
|---|---|
| 数据安全性高(最多丢 1 秒) | 文件比 RDB 大 |
| 日志可读、可修复 | 恢复比 RDB 慢(要重放命令) |
4. 混合持久化(Redis 4.0+,当前推荐)
Redis 现在支持两者结合,取长补短:
aof-use-rdb-preamble yes # Redis 7 默认开启
原理:AOF 重写时,先把当时的全量数据以 RDB 格式写入 AOF 文件开头,之后的增量命令继续以 AOF 格式追加。恢复时:先快速加载 RDB 部分,再重放少量增量命令——恢复快 + 丢数据少,两全其美。
5. 实际工作中怎么配?
| 场景 | 建议 |
|---|---|
| 纯缓存,数据丢了无所谓(可从数据库重建) | 甚至可以关闭持久化,或只留 RDB |
| 一般业务(推荐起点) | AOF 开启 + everysec + 混合持久化(即 Redis 7 默认 + appendonly yes) |
| 数据极其重要 | AOF always,并配合主从复制、异地备份 |
推荐的最小配置:
appendonly yes
appendfsync everysec
aof-use-rdb-preamble yes
save 3600 1 300 100 60 10000
6. 动手实验
体验持久化的效果(Docker 用户注意启动时要带 --appendonly yes):
redis-cli set important-data "hello"
redis-cli bgsave # 手动做一次快照
# 重启 Redis(docker restart my-redis 或 systemctl restart redis)
redis-cli get important-data # 数据还在!
再对比:如果 RDB 和 AOF 都关掉,重启后数据就没了。
7. 小结(面试速答版)
- RDB:定时全量快照,恢复快、文件小,但两次快照间的数据会丢;
bgsave通过 fork 子进程避免阻塞 - AOF:记录每条写命令,默认每秒刷盘(最多丢 1 秒);文件大了会自动重写压缩
- 混合持久化:AOF 文件 = RDB 全量打底 + AOF 增量,是当前的推荐方案
- 纯缓存可以不开持久化,重要数据用 AOF everysec 起步
下一章:把多条命令打包执行 👉 03 事务与 Lua 脚本