跳到主要内容

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 脚本