Redis 里 RDB 和 AOF 的区别
学 Redis 持久化的时候,RDB 和 AOF 是很容易混的两个点。
它们的目的都一样:让 Redis 重启后还能恢复数据。
但是它们保存数据的思路完全不一样:
RDB:保存某一时刻的数据结果AOF:保存每一次写操作的命令过程
说白了:
RDB 像"拍照片",AOF 像"记流水账"。
一、先用一张图看整体区别
Redis 内存数据
RDB:生成快照文件 dump.rdb
AOF:追加写命令 appendonly.aof
重启时直接加载快照结果
重启时重新执行写命令
这张图就能看出核心区别:
RDB保存的是内存数据的最终状态AOF保存的是修改数据的命令记录
二、RDB 是什么
RDB 可以理解成 Redis 给当前内存数据做了一次"快照"。
比如我执行了:
redis
SET name a
SET name b
SET name c
如果这时候 Redis 生成一次 RDB 文件,它不会关心你前面改了几次,只关心当前最终结果。
最终保存的效果更像是:
text
name = c
这里要记住:RDB 不记录修改过程,只记录某一时刻的最终数据。
三、RDB 的底层大概怎么做
RDB 持久化不是主进程自己慢慢把数据写完再继续干活。
它通常会通过 fork 创建一个子进程,让子进程负责把内存数据写成 RDB 文件。
大概流程是这样:
Redis 主进程
触发 RDB 保存
fork 出子进程
子进程读取当前内存数据
写入临时 RDB 文件
替换旧的 dump.rdb
主进程继续处理客户端请求
这里有一个底层点要知道:
fork 之后,子进程看到的是 fork 那一刻的数据状态。后面主进程继续处理新的写命令,操作系统会通过写时复制机制处理内存变化。
不用把这个机制背得特别深,先理解成:
RDB 保存的是 fork 那一刻的快照,不是实时不断变化的过程。
四、AOF 是什么
AOF 全称是 Append Only File,可以理解成"追加日志文件"。
Redis 每执行一条会修改数据的命令,就把这条命令追加到 AOF 文件里。
比如:
redis
SET name a
SET name b
SET name c
AOF 一开始记录的通常就是:
redis
SET name a
SET name b
SET name c
也就是说,AOF 保存的是:
你是怎么一步一步把数据改成现在这样的。
五、AOF 的底层大概怎么写
AOF 不是简单一句"写到文件"就结束了。
它中间还有一个比较重要的问题:什么时候真正刷到磁盘?
大概流程可以这样看:
客户端发送写命令
Redis 执行命令,修改内存
把写命令追加到 AOF 缓冲区
write 写入操作系统缓存
fsync 按策略刷到磁盘
appendonly.aof 文件
这里有个关键配置:
conf
appendfsync always
appendfsync everysec
appendfsync no
这三个配置的意思是:
always:每次写命令都刷盘,最安全,但性能最差everysec:每秒刷一次盘,比较常用,最多可能丢 1 秒数据no:交给操作系统决定什么时候刷盘,性能好,但风险更大
一般学习和实际使用里,最常见的是:
conf
appendfsync everysec
六、用一个例子真正分清楚
比如我执行下面这些命令:
redis
SET k1 1
INCR k1
INCR k1
DEL k1
SET k2 hello
如果是 AOF
AOF 关心的是过程,所以它可能记录:
redis
SET k1 1
INCR k1
INCR k1
DEL k1
SET k2 hello
如果是 RDB
RDB 关心的是结果。
最后 k1 已经被删了,只剩:
text
k2 = hello
所以可以发现:
- AOF 会知道
k1曾经经历过什么 - RDB 只知道最后
k1已经不存在
七、AOF 重写又是什么
这里是另一个容易混的地方。
AOF 一直追加命令,文件会越来越大。
比如:
redis
SET name a
SET name b
SET name c
如果一直保留这些命令,前两条其实已经没意义了,因为最后结果就是 name = c。
所以 Redis 会进行 AOF 重写,把旧日志压缩成更短的新日志。
旧 AOF:SET name a
SET name b
SET name c
AOF 重写
新 AOF:SET name c
注意:
AOF 平时记录过程,AOF 重写后才会尽量整理成最终有效结果。
所以不能简单说"AOF 只保存最后结果"。
更准确的说法是:
- 平时 AOF:记录每一次写操作
- AOF 重写后:把没必要的旧操作压缩掉
八、Redis 重启时怎么恢复
Redis 重启时,如果有持久化文件,就会把数据恢复到内存里。
恢复流程可以这样理解:
是
否
是
否
Redis 启动
是否开启 AOF 并存在 AOF 文件?
优先加载 AOF
重新执行 AOF 里的写命令
恢复内存数据
是否存在 RDB 文件?
加载 RDB 快照
空数据启动
这里要记住:
如果同时开启了 RDB 和 AOF,Redis 通常会优先用 AOF 恢复,因为 AOF 往往数据更完整。
九、RDB 和 AOF 对比表
| 对比点 | RDB | AOF |
|---|---|---|
| 保存内容 | 某一时刻的数据结果 | 每一次写操作命令 |
| 理解方式 | 拍快照 | 记日志 |
| 文件大小 | 通常较小 | 通常较大 |
| 恢复速度 | 通常较快 | 通常较慢 |
| 数据安全性 | 可能丢最近一次快照后的数据 | 一般丢失更少 |
| 适合场景 | 备份、快速恢复 | 尽量减少数据丢失 |
十、怎么记最简单
我觉得最容易记的方式就是三句话:
RDB:我现在有什么数据AOF:我执行过哪些写命令AOF 重写:把旧命令整理成更短的新命令
再压缩一下就是:
RDB 看结果,AOF 看过程。
十一、小结
RDB 的底层重点是:Redis 在某个时间点 fork 子进程,把当时的内存数据写成快照文件。
AOF 的底层重点是:Redis 执行写命令后,会把命令追加到 AOF 里,再根据刷盘策略写入磁盘。
所以最后总结一句:
RDB 记录某一刻的最终数据,AOF 记录数据变化的操作过程。