连载中 10/16

持久化:RDB 与 AOF,快照和日志怎么选

2026-05-20 · 6984 阅读 · 0 评论 · 0 赞

机房闪断三分钟,缓存从零开始

接着讲大促系列的事故。那次机房闪断,Redis 进程重启了,几百万个缓存 key 灰飞烟灭。重启完成的那一刻,缓存命中率从 98% 直接归零,上万请求同时扑向数据库——第 6 篇讲的「冷启动二次雪崩」,我们真真切切体验了一遍。那次之后我记住了两件事:一是缓存实例的持久化必须配置到位,二是内存数据想活过断电,就得提前把账记在磁盘上

Redis 提供两条记账思路:RDB 是「拍快照」,每隔一段时间把全量数据拍成一张二进制照片;AOF 是「记流水」,每条写命令都记进日志,重启时从头重放一遍。一个管存量、一个管增量,取舍贯穿始终。

RDB:fork 子进程,拍一张全量快照

RDB 的执行者是 fork 出来的子进程,主进程继续服务,这就是 bgsave 不阻塞读写的原因。而 fork 的魔法在于操作系统的写时复制:父子进程一开始共享同一批内存页,谁写谁复制一份,子进程看到的永远是 fork 那一瞬间的数据快照,稳稳地往磁盘写。

# redis.conf:满足任一条件自动 bgsave
save 900 1      # 900 秒内有 1 次写
save 300 10     # 300 秒内有 10 次写
save 60 10000   # 60 秒内有 1 万次写
dbfilename dump.rdb

RDB 的优点很硬:二进制文件紧凑,传输和恢复都快——重启时直接把快照读进内存,几个 G 的数据几十秒完事。缺点同样直接:两次快照之间的写入,宕机就没了。另外 fork 本身虽然「瞬时」,但要复制页表,几十 G 的大实例会有明显毛刺;写越密集,写时复制额外占用的内存越多,极端情况下内存接近翻倍。

AOF:每条写命令都记账

AOF 走的是另一条路:把每条写命令以文本形式追加进日志,重启时逐条重放,数据就回来了。有个值得咂摸的细节:AOF 是写后日志——先执行命令、再记日志。好处是不阻塞当前写操作,还能避免把执行失败的错误命令记进账本;代价是命令执行完、日志没落下时宕机,这条数据就丢了。

丢多少,取决于日志什么时候真正刷到磁盘,由 appendfsync 控制:

配置刷盘时机丢失窗口性能
always每条命令都刷盘几乎不丢最差,磁盘扛不住高写入
everysec由后台线程每秒刷一次最多丢 1 秒折中,生产推荐
no交给操作系统决定不可控最好,但别这么配

AOF 还有个成长烦恼:同一个 key 改一百次,日志里就躺着一百条命令,文件越来越肥,恢复越来越慢。解法是 AOF 重写——还是 fork 子进程,按当前内存里的最终状态生成一份「最小命令集」,一百次修改压成一条 SET。重写期间的新写入由缓冲区兜着,不会丢。

# redis.conf:开启 AOF 并配置自动重写
appendonly yes
appendfsync everysec
# 文件比上次重写后大 100% 且超过 64mb 时触发重写
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

混合持久化:快照开头,流水续尾

RDB 恢复快但丢得多,AOF 丢得少但恢复慢——4.0 的混合持久化把它们缝在了一起:重写 AOF 时,先以 RDB 格式写入当前全量数据做文件头,之后的增量写命令继续以 AOF 格式追加。重启恢复时,RDB 头几秒加载完,再重放少量增量日志,快和全兼得。开启只需一行:

# redis.conf:AOF 重写时使用 RDB 格式的文件头
aof-use-rdb-preamble yes

两种方案放在一起看:

维度RDBAOF
本质某一刻的全量快照(二进制)每条写命令的流水(文本)
数据安全两次快照之间的写入会丢everysec 最多丢 1 秒
文件体积小,紧凑大,依赖重写瘦身
恢复速度快,直接加载慢,逐条重放
性能影响fork 瞬间毛刺 + 写时复制持续的 fsync 磁盘开销

怎么选:看 Redis 在你架构里扮演谁

  • 纯缓存,数据随时能从数据库重建:RDB 就够,甚至可以只开低频快照;重启后靠回源预热,别为「丢了也无所谓」的数据付出 AOF 的持续磁盘开销。记得第 6 篇的教训:重启后先预热再放量,防冷启动雪崩。
  • 当准存储用(会话、排行榜):混合持久化 + everysec,恢复快、丢失少,绝大多数场景的最优解。
  • 一条都不能丢的数据:说真的,别把它放 Redis。持久化再强也扛不住磁盘和机器一起没,关键数据以数据库为准,Redis 只做加速。

补一个运维细节:线上执行过 FLUSHALL 这种高危命令的话,RDB 和 AOF 会忠实地把「清空」也记录下来——所以清库不只是数据没了,连后悔药都被涂掉了一半。建议在配置里用 rename-command 把这类命令改名禁用,真出事时 AOF 文件还能用 redis-check-aof --fix 抢救到最后一条完整的命令。


一句话总结:RDB 管快、AOF 管全、混合持久化管「既要又要」,而选型的锚点只有一个——Redis 在你的架构里是缓存还是存储。下一篇聊聊主从复制:数据怎么从主库流向从库?全量同步和增量同步的分界在哪?主从延迟又该怎么办?下篇见。

咖啡凉了,记得趁热喝。

503

10 年全栈工程师 · 503咖啡馆主理人

#Redis#持久化#RDB#AOF#混合持久化

评论 (0)

相关推荐

连载中 12/20

排查四件套:jstack、jmap、jstat、jcmd 的实战分工

jstack 看线程在干什么,jmap 看堆里装了什么,jstat 看运行时在变什么,jcmd 是统一入口。四把刀各管一段,配合着用没有查不动的现场。

#jstack#jmap#jstat#jcmd#排查工具
2026-09-16 · 5 阅读 · 0 评论 · 0 赞
连载中 11/20

GC 日志:把回收过程翻译成人话

一行 GC 日志里塞着七种信息:谁触发的、收了哪、停了多久、活了哪些。加上 -Xlog 配置,再加上日志分析工具,GC 不再是只能盯监控曲线的黑盒。

#GC日志#Xlog#日志分析#GC监控#Full GC排查
2026-09-16 · 13 阅读 · 0 评论 · 0 赞
连载中 10/20

ZGC:亚毫秒停顿是怎么炼成的

百 G 大堆停顿不到一毫秒,靠的是把搬家全部挪到并发阶段——着色指针让引用自带状态,读屏障让搬运中的对象依然可访问。代价是吞吐与内存,收益是停顿与堆大小解耦。

#ZGC#着色指针#读屏障#亚毫秒停顿#分代ZGC
2026-09-15 · 8 阅读 · 0 评论 · 0 赞