Redis 持久化:断电了数据怎么不丢?RDB 和 AOF 怎么选

0 阅读4分钟

Redis 持久化:断电了数据怎么不丢?RDB 和 AOF 怎么选

作者:鱼宵 | 实战驱动系列 · 第 9 篇

完整课程与可运行源码已开源在 Gitee:gitee.com/j67mk2/redi… (本文对应 lesson-03/)


一、问题:内存数据库,宕机了数据不就全没了?

Redis 快,是因为数据都放内存里。但内存有个致命缺点:断电/进程退出就清空。如果里面存的是库存、登录会话,一重启全没了,业务直接崩。

所以 Redis 提供了两种"存盘"手段:RDB 和 AOF。这篇把它们拆透,并亲手触发一次快照看到文件生成。


二、RDB:拍快照(拍照片)

类比:给当前整个柜子"拍一张照片"。咔嚓一下,把此刻所有东西的样子存成 dump.rdb 文件。

  • 什么时候拍:
    1. 按配置自动拍——Redis 7 默认规则 save 3600 1 300 100 60 10000,意思是:1 小时内至少 1 个 key 变了拍一次;5 分钟内至少 100 个 key 变了拍一次;60 秒内至少 1 万个 key 变了拍一次。(老教程常见的 save 900 1 意思一样:900 秒内 1 个 key 变了就拍。)
    2. 手动拍——save(阻塞式,卡住主进程,生产别用)或 bgsave(后台 fork 子进程去拍,推荐)。
    3. 正常关闭时 shutdown 自动存一次。
  • 优缺点:👍 文件小、恢复飞快(直接把文件灌回内存)。👈 两次快照之间新写的数据会丢——1 小时拍一次,拍完后第 59 分钟宕机,这 59 分钟数据全没了,丢数据窗口大。

亲手触发一次(实测):

$ docker exec redis-l3 redis-cli BGSAVE
Background saving started

$ docker exec redis-l3 ls -lh /data
-rw------- 1 redis redis 161 Oct  2 07:50 dump.rdb   <- 快照文件出现了

$ docker exec redis-l3 redis-cli INFO persistence
rdb_last_bgsave_status:ok     <- 快照成功

三、AOF:记账本(append-only file)

类比:RDB 是拍照片,AOF 是记账本。不拍整张照片,而是把"每一条写命令"都像记账一样追加记到 appendonly.aof。重启时把本子上的命令从头到尾再执行一遍,数据就回来了。

  • 怎么做:SET a 1、INCR counter 这些写命令都会被记下来,读命令(GET)不记。
  • 多久写一次(appendfsync 三档):
配置人话安全 vs 性能
always每写一条就立刻刷盘最安全,但最慢
everysec每秒刷一次盘(默认)折中:最多丢 1 秒
no交给操作系统最快,丢多少不可控
  • AOF 重写(bgrewriteaof):记账本会越来越厚。你对同一个 key set age 1 → set age 2 → set age 3,本子上记了 3 条,其实最后只要 set age 3 一条就够了。类比:账本太厚了重新誊一遍,把啰嗦的旧命令压缩成"最少能还原当前状态"的几条,文件就瘦了。

亲手开启 AOF(实测):

$ docker exec redis-l3 redis-cli CONFIG SET appendonly yes
OK

$ docker exec redis-l3 ls -lh /data/appendonlydir
-rw------- 1 redis redis 217 Oct  2 07:51 appendonly.aof.1.base.rdb
-rw------- 1 redis redis   0 Oct  2 07:51 appendonly.aof.1.incr.aof
-rw------- 1 redis redis  88 Oct  2 07:51 appendonly.aof.manifest

注意那个文件名:appendonly.aof.1.base.rdb——后缀是 .rdb!这就是 Redis 7 混合持久化的铁证:AOF 的基础部分用 RDB 格式存,增量命令记在 incr.aof,manifest 是清单。老教程说"看 appendonly.aof",在 Redis 7 里找不到——去 appendonlydir 目录看。


四、混合持久化:既要又要

RDB 恢复快、AOF 数据安全,能不能都占?Redis 4.0 引入 aof-use-rdb-preamble(混合持久化):AOF 重写时,前半段用 RDB 格式存全量快照,后半段记增量命令。既享受 RDB 恢复快,又保留 AOF 少丢数据。Redis 7 默认就是这么干的。


五、一张表总结(面试直接背)

RDB(拍快照)AOF(记账本)
存的是什么某一时刻全量数据的二进制快照一条条写命令
文件dump.rdbappendonly.aof.*(Redis 7 拆 base+incr+manifest)
丢数据多(两次快照之间)少(everysec 最多丢 1 秒)
恢复速度快慢(要重放命令)
文件体积小大
适合备份、容灾、能容忍丢一点对数据安全要求高

能不能都开? 能,生产推荐都开:RDB 做冷备份/快速恢复,AOF 保证少丢数据。


六、挑战题

  1. ⭐ 亲手触发一次 BGSAVE,用 ls -lh /data 看到 dump.rdb 从无到有。
  2. ⭐⭐ 故意 CONFIG SET appendonly no 关掉 AOF,docker restart 后数据还在吗?反过来只开 RDB,宕机后两次快照之间新写的数据还在不在?动手验证"丢数据窗口"。
  3. ⭐⭐⭐ 给一个"不能丢订单数据"的生产 Redis 选持久化方案:写出你的 save 规则、appendonly、appendfsync 选择,并说明理由。

七、面试回答模板

面试官:RDB 和 AOF 区别?

RDB 是拍快照,存某一时刻全量数据的二进制文件,文件小、恢复快、但丢数据窗口大;AOF 是记账本,记每一条写命令,更安全(everysec 最多丢 1 秒)但文件大、恢复慢。

追问:能不能都开?

能,生产推荐都开,RDB 做冷备份、AOF 保证少丢;Redis 4.0+ 混合持久化把两者结合——AOF 重写时前半段 RDB 后半段 AOF。

追问:AOF 重写原理?

fork 子进程把当前数据重新算成最小命令集写新文件,期间新命令记在缓冲区最后追加;写时复制(COW)让父进程继续接业务,不会卡住。


关于这个系列

本文是「Java 后端实战精通营」系列第 9 篇,原则:实战驱动、由浅到深、面试向。

👉 Redis 实战精通营(10 课):gitee.com/j67mk2/redi…

  • 本文对应源码位置:lesson-03/(Java 触发 BGSAVE + 查持久化配置的 demo)

下一篇预告:《Redis 过期策略与内存淘汰:缓存穿透/击穿/雪崩一次讲透》——数据放多久该删、内存满了踢谁、面试必考的缓存三兄弟。

跑完有任何报错,把终端输出发评论区,一起排查。