BodySense Redis 第 7 课:Persistence——RDB、AOF 与 Recovery
从 Redis 是内存系统出发,学习 RDB、AOF、fsync、重启恢复,以及为什么“有持久化”仍不等于“适合做长期业务事实源”。
[!info] related notes
- 课程 MOC:BodySense Redis 从零到一课程 MOC
- 前置课程:第 6 课
- 对应知识笔记:Redis RDB、AOF 与恢复、Redis
- 项目:BodySense 云原生基础设施规划
BodySense Redis 第 7 课:Persistence——RDB、AOF 与 Recovery
[!abstract] 学习目标 理解:Redis 以内存工作,不代表它一定“重启全丢”;Redis 能持久化,也不代表它自动等价于 PostgreSQL。
先区分四个很容易混在一起的词
这一课最容易犯的错误,是把 Persistence、Durability、Backup、System of Record 全部叫“持久化”。
Persistence
Redis 进程重启或内存丢失后,能否根据磁盘上的数据恢复。
典型手段:RDB / AOF。
Durability
一个已经被系统确认成功的写入,在崩溃后还能保留到什么程度。
它关心的是“已经告诉客户端成功之后,最多还可能丢多少”。
Backup
与在线实例解耦的一份历史副本,用来应对误删、损坏、灾难或回到旧时间点。
System of Record / Source of Truth
从业务架构上,哪套系统拥有这份事实的权威。
所以:
Redis 开 AOF
≠ Redis 自动成为 PostgreSQL 的替代品
PostgreSQL 是 truth
≠ 所有 Redis 都不需要 persistence
这是本课贯穿始终的边界。
为什么“内存里的数据”进程一停就会消失
应用运行时的 RAM 可以粗略想成:
Redis process
└─ address space / RAM
├─ keys
├─ values
└─ metadata
如果机器断电或进程退出,RAM 中的数据不会像磁盘文件那样天然长期保存。
因此 Redis 若承载:
纯 Cache
→ 可以接受 cold rebuild
Session / Refresh authority
→ 全丢会造成大批用户被迫重新登录
这两类实例对 Persistence 的需求可以完全不同。
为什么内存数据库还需要持久化
Redis 的工作数据主要在内存:
request
→ memory data structure
→ response
但如果进程退出:
memory disappears
对纯 Cache:
可以重建
对 Session / Refresh authority:
可能导致大批用户掉登录
因此是否启用持久化,取决于数据丢失语义和恢复目标。
RDB Snapshot:把某个时间点的内存状态拍成快照
RDB = Redis Database snapshot。
可以把它类比成:
12:00
Redis memory state
→ 拍照
→ dump.rdb
恢复时不是逐条重放历史命令,而是把快照中的数据集加载回内存。
RDB 的优点
- 文件通常比较紧凑;
- 适合作为时间点快照;
- 恢复时直接加载数据集;
- 对长期归档/传输比不断增长的原始命令历史更自然。
RDB 的核心 trade-off
如果:
12:00 snapshot
12:05 process crashes
而这 5 分钟没有新的 snapshot / 其他 persistence:
12:00 ~ 12:05 的写入
→ 不在那份 RDB 中
所以 RDB 的 durability window 与 snapshot 频率相关。
Background Save 为什么还会带来成本
Redis 常用后台子进程生成 snapshot。在支持 fork 的系统上,这涉及 fork + copy-on-write。
可以先建立直觉:
父进程继续服务请求
子进程写 snapshot
如果 snapshot 期间大量内存页继续被修改,copy-on-write 会带来额外内存压力;同时还有磁盘 I/O。
所以“后台保存”不等于“完全没有性能成本”。
AOF:记录写操作,让 Redis 可以重放历史恢复状态
AOF = Append Only File。
思路和 RDB 不同:
RDB
→ 保存“某个时间点现在长什么样”
AOF
→ 保存“哪些写操作改变了数据”
例如概念上记录:
SET a 1
SADD user_sessions:u1 s1
DEL session:s2
...
重启时:
read persisted AOF
→ replay effects
→ rebuild in-memory dataset
Redis 官方当前文档中,Redis 7 起使用 multi-part AOF:通常由 base file + 后续 incremental files 组成,并由 manifest 管理。这个实现细节不改变核心心智模型:AOF 仍然是通过持久化写入效果来支持恢复。
Append Only 不等于“每个命令立刻进物理磁盘”
操作系统本身有 page cache / write buffer。
粗略链路:
Redis
→ write()
→ OS buffer/page cache
→ fsync / storage flush
→ durable storage
因此 appendfsync 的意义就是决定 Redis 多积极地要求操作系统把 AOF 数据刷到持久介质。
appendfsync
重要选项:
always
每次写入都尽量 fsync
更强 durability,I/O 代价更高。
everysec
大约每秒 fsync
常见折中:
性能较好
+
极端 crash 时可能损失约一小段最近写入
no
把 fsync 调度更多交给操作系统,性能更轻,但 durability window 更不明确。
BodySense 当前配置
生产 Redis 当前已经:
appendonly yes
appendfsync everysec
persistent volume
这意味着:
Redis 不只是“进程死了必然全清空”的纯临时实例。
但仍需问:
AOF 文件所在 volume 是否可靠?
恢复是否验证过?
容灾 / backup 是否存在?
failover 时复制语义如何?
Persistence ≠ Backup
这两个概念必须分开。
Persistence
→ 进程重启后尽量恢复最近状态
Backup
→ 有独立时间点副本,可在误删、损坏、灾难后恢复
如果操作员错误执行:
DEL critical:key
AOF 可能忠实记录这个删除。
所以:
“有 AOF”并不能代替备份和灾难恢复设计。
Persistence ≠ System of Record
这是本课最重要的判断。
即使 Redis 有 AOF:
BodyState
Diagnosis
Treatment
Runtime Event durable log
Job ledger
仍然不应因此默认迁成 Redis-only。
这些状态通常需要:
- 关系约束;
- 多实体事务;
- 历史查询;
- 审计;
- replay;
- durable ownership;
- 数据迁移与分析。
Redis 持久化解决的是:
Redis 自己的恢复能力。
而 PostgreSQL 的 domain authority 是另一层架构问题。
AOF Rewrite:日志可以压缩成“重建当前状态所需的最小效果”
如果 AOF 永远只是追加:
SET counter 1
SET counter 2
SET counter 3
...
SET counter 1000000
文件会不断增大。
但恢复当前状态并不需要保留每一次历史覆盖。
理论上当前结果只需要类似:
SET counter 1000000
所以 Redis 会进行 AOF rewrite:
old AOF history
→ 根据当前 dataset 生成更紧凑 base
→ 继续接收增量写
→ 切换到新的 AOF 组合
这不是“修改历史业务审计日志”,因为 AOF 本来就不是给人做业务审计的 event log;它的目标是恢复 Redis 当前数据集。
Rewrite 也有资源成本
需要关注:
CPU
memory / copy-on-write
disk throughput
disk free space
rewrite duration
latency spike
所以运维上不仅要问:
AOF 开了吗?
还要问:
rewrite 是否健康、磁盘是否够、恢复有没有实际验证过?
RDB + AOF
不是只能二选一。
可以同时使用:
RDB
→ 快照 / 备份友好
AOF
→ 更细粒度写入恢复
最终策略由:
可接受数据丢失窗口
恢复时间
I/O 预算
数据是否可重建
决定。
BodySense 思考题
如果 Redis 丢掉最近 1 秒:
Session
可能:
刚创建的 Session 消失
→ 用户刚登录就被迫重新登录
Refresh Rotation
更微妙:
旧 token consumed / replay tombstone
新 token active
如果 crash/recovery 回到一个不一致的时间点,必须确认安全语义是否仍可接受。
所以不能只说:
“AOF everysec 很安全。”
而要具体分析每种 key 的 recovery semantics。
Lab
在开发环境隔离实验:
1. 写入带 TTL / 不带 TTL 的 Key
2. restart Redis container
3. 检查恢复
4. 查看 AOF / persistence INFO
5. 在独立实验配置下比较 no persistence / AOF / RDB
不要直接修改生产策略。
Prediction
[!question]
- RDB 和 AOF 最直观的区别是什么?
- appendfsync everysec 是否意味着绝对不会丢最近 1 秒?
- 有 AOF 后,Redis 能否自动取代 PostgreSQL 成为 BodyState 的唯一事实源?
- Persistence 为什么不能替代 Backup?
- 对一个纯 Cache Redis,是否一定需要 AOF?
[!success]- Answer / 解析 1. RDB 和 AOF 最直观的区别是什么?
RDB 保存某个时间点的状态快照;AOF 记录可重放的写操作历史。前者更像定期拍照,后者更像持续记账。2. appendfsync everysec 是否意味着绝对不会丢最近 1 秒?
不是。它表示常见策略是大约每秒把 AOF 刷到持久存储,是 durability 与性能的折中,不是严格“最多只丢 1.000 秒”的数学保证。操作系统调度、硬件、崩溃类型和底层存储都可能影响实际窗口。3. 有 AOF 后,Redis 能否自动取代 PostgreSQL 成为 BodyState 的唯一事实源?
不能。AOF 提升的是 Redis 自身的恢复能力;BodyState 是否应由 PostgreSQL 持有,取决于事务、关系约束、历史审计、查询、数据治理和 domain ownership。durable Redis 不等于 relational domain database。4. Persistence 为什么不能替代 Backup?
Persistence 会忠实保存很多错误操作。例如误执行 DEL critical:key,AOF 也可能把删除记录下来。Backup 是与在线实例解耦的历史恢复点,主要解决误删、损坏、灾难和时间点恢复问题。5. 纯 Cache Redis 是否一定需要 AOF?
不一定。如果所有数据都能从 PostgreSQL 等事实源安全重建,而且可以接受 Redis 重启后的 cold cache,那么关闭持久化可能更简单。是否启用应由重建成本、恢复时间和用户体验决定,而不是“生产 Redis 必须 AOF”。
L4 Gate
能根据四个问题做持久化决策:
Redis 数据能否重建?
最多能接受丢多少?
恢复要多快?
持久化 I/O 对延迟是否可接受?
并解释:
durability 是存储属性,system of record 是业务所有权属性。两者不是同一个维度。