适合人群:用过 Redis 当缓存,但没想过”断电之后数据怎么办”的同学。
本篇基于 Redis 7.x(AOF 的多文件机制以 7.0 为准),配置可直接复制。
一、内存很快,但断电就没了
Redis 的全部数据都在内存里,这意味着:进程一挂、机器一断电,数据全没。
对纯缓存场景,丢了可以回源重建,问题不大。但如果 Redis 里存的是计数器、分布式锁、延迟队列、购物车——丢了就是业务事故。所以 Redis 需要持久化:在”内存性能”和”数据安全”之间做权衡,把内存数据设法落到磁盘。
Redis 给出两套方案,思路完全不同:
- RDB:定时拍快照——某一时刻内存数据的完整照片,二进制压缩存盘
- AOF:记日志——把每一条写命令追加到文件,重启时重新执行一遍
二、RDB:定时拍照
怎么触发
1 | # 手动触发(生产慎用 SAVE:阻塞主线程) |
核心:fork + 写时复制(COW)
BGSAVE 时 Redis 会 fork() 出一个子进程去生成 RDB 文件。问题来了:拍照要遍历全量数据,期间主线程还在接写命令,子进程怎么拍出一份”一致性”的快照?
答案是操作系统的写时复制(Copy-On-Write):
- fork 出的子进程和父进程共享同一份物理内存页(只读)
- 子进程安心遍历内存生成 RDB 文件
- 父进程继续处理写命令——一旦要修改某个内存页,内核才把那一页复制一份给父进程改
- 结果:子进程看到的永远是 fork 那一瞬间”冻结”的数据版本
这是面试高频考点:BGSAVE 期间 Redis 会不会卡? fork 本身很快(复制的是页表不是内存),但数据量很大时页表复制也有几十到几百毫秒的停顿;之后主线程不受影响,代价只是写命令会多一次页复制。
RDB 的优缺点
优点:文件紧凑(压缩二进制)、恢复极快(直接载入)、适合容灾备份(一个文件拷走就行)。
缺点:两次快照之间的数据会丢。比如 save 300 10,最坏丢整整 5 分钟数据;fork 在大内存实例上开销不小。
三、AOF:把每条写命令记下来
三种刷盘策略
AOF 的流程是:写命令先进入 aof_buf 缓冲区,再由 appendfsync 决定多久真正写到磁盘:
1 | appendonly yes |
everysec 是官方默认,也是绝大多数场景的最优解:至多丢 1 秒数据,性能损耗很小。
AOF 重写:日志不能无限膨胀
问题:INCR counter 执行 100 万次,AOF 里就是 100 万条记录——counter 的 100 万个历史值毫无意义,恢复只需要最后一条 SET counter 1000000。
AOF 重写(BGREWRITEAOF)就是:fork 子进程,根据当前内存状态生成一份最精简的日志(等价于”用现在的数据反推最少的命令”),替换旧文件。重写期间的新写命令写入重写缓冲区,最后追加到新文件。
Redis 7.0 起 AOF 从单文件变成 multi-part AOF:基础文件(base,可能是 RDB 格式)+ 增量文件(incr)+ 一个 manifest 清单统一管理,重写不再需要”重写缓冲区追加”的老机制,实现更干净。
AOF 的优缺点
优点:丢数据少(everysec 最多丢 1 秒),日志是可读的追加命令,甚至能手动修复。
缺点:文件比 RDB 大、恢复慢(要逐条重放命令)、每秒 fsync 也有一点点性能开销。
四、混合持久化:两个都要(Redis 4.0+)
RDB 恢复快但丢得多,AOF 丢得少但恢复慢——于是 Redis 4.0 推出混合持久化,直接缝合两者优点:
1 | aof-use-rdb-preamble yes # Redis 7.x 里等价于 aof-timestamp-enabled 时代的默认行为 |
原理:AOF 重写时,先把当前全量数据以 RDB 格式写入新 AOF 文件的开头,之后的增量写命令再以 AOF 格式追加在后面。
恢复时:先加载 RDB 部分(快),再重放增量 AOF 命令(少)。
- 丢数据窗口 = AOF 的 everysec(最多 1 秒)
- 恢复速度 ≈ RDB 的载入速度 + 少量命令回放
这就是目前生产环境的默认选择。
五、生产环境怎么选?
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 纯缓存,丢了能回源 | RDB(或干脆关持久化) | 恢复快、省心 |
| 存了业务数据(计数、队列、购物车) | 混合持久化 | 丢得少 + 恢复快 |
| 金融级、一条都不能丢 | everysec + 业务层补偿(如事务消息) | Redis 本质不是数据库,兜底要在业务做 |
一份可以直接抄的配置:
1 | # redis.conf 持久化部分(Redis 7.x) |
总结
- RDB 是快照:fork + 写时复制,恢复快,会丢两次快照之间的数据
- AOF 是日志:appendfsync 三档,everysec 兼顾性能与安全;重写解决膨胀
- 混合持久化 = RDB 打底 + AOF 增量,生产首选
- 记住那条主线:持久化的一切设计,都是”性能”与”数据安全”的权衡
下一篇讲使用 Redis 做缓存绕不开的三大经典故障:缓存穿透、缓存击穿、缓存雪崩——以及缓存和数据库的一致性怎么保。