目录
2.3 BGSAVE 的底层原理:Copy-On-Write
Redis 作为内存数据库,数据都放在内存里。一旦进程退出或服务器宕机,内存数据就全没了。所以持久化是 Redis 数据安全的第一道防线,也是面试和实际运维中都绕不开的核心话题。
1. Redis 持久化的两种思路
Redis 提供了两种完全不同的持久化方式:
-
RDB(Redis Database):快照,把某个时间点的内存数据直接写到磁盘文件里。
-
AOF(Append Only File):日志,记录每一次写命令,重启时重放这些命令来恢复数据。
两种方式可以单独使用,也可以同时开启。
2. RDB 快照持久化
2.1 RDB 是什么
RDB 就是把 Redis 某一时刻的全量内存数据保存到一个二进制文件(默认叫 dump.rdb)中。
可以想象成给 Redis 的内存拍了一张照片,这张照片记录了拍照那一刻的所有数据。如果 Redis 挂了,用这张照片就能恢复到拍照时的状态。
2.2 RDB 的触发方式
方式一:手动触发
# 同步阻塞保存,主线程执行,保存期间不处理任何请求
SAVE
# 异步后台保存,fork 子进程执行,主线程继续处理请求
BGSAVE
-
SAVE:生产中禁用。它会在主线程中执行,如果数据量大,会阻塞所有客户端请求长达数秒甚至更久。 -
BGSAVE:推荐使用。Redis 会 fork 一个子进程,子进程负责把数据写入磁盘,主进程继续处理请求。
方式二:自动触发(配置 save 参数)
# redis.conf 中的配置(默认值)
save 900 1 # 900 秒内至少 1 次修改,触发 BGSAVE
save 300 10 # 300 秒内至少 10 次修改,触发 BGSAVE
save 60 10000 # 60 秒内至少 10000 次修改,触发 BGSAVE
多条 save 规则只要满足任意一条,就会自动触发一次 BGSAVE。这个机制非常实用,我们不需要手动执行备份,系统会根据数据变化频率自动保存。
如果不需要自动 RDB,可以注释掉所有 save 行,或者写 save ""。
方式三:通过 LASTSAVE 查看上次保存时间
# 查看上次 BGSAVE 成功执行的时间戳
LASTSAVE
返回值是一个 Unix 时间戳,可以转换为可读时间。运维时可以用它来判断备份是否按时执行。
2.3 BGSAVE 的底层原理:Copy-On-Write
BGSAVE 之所以能在备份的同时不阻塞读写,靠的是操作系统提供的写时复制(Copy-On-Write,COW)机制。
执行流程如下:
-
Redis 主进程调用
fork()创建一个子进程。 -
刚 fork 完的那一刻,父子进程共享同一块物理内存(内存页表相同)。
-
子进程开始遍历内存数据,写入 RDB 文件。
-
在此期间,如果主进程需要修改某个数据(比如
SET),操作系统会把包含该数据的内存页复制一份,主进程在新页面上修改,子进程继续读旧页面。 -
子进程完成写入后退出,RDB 文件生成完毕。
整个过程,主进程基本不受影响,只是 fork 那一瞬间需要短暂停顿。
重点理解:fork() 的速度和 Redis 实例的内存大小直接相关。内存越大,页表越大,fork 越慢。对于几十 GB 的大实例,fork 可能耗时几百毫秒甚至上秒,这期间主线程是阻塞的。
2.4 RDB 文件的修复与检查
# 检查 RDB 文件是否有损坏
redis-check-rdb dump.rdb
# 如果损坏,可以尝试修复(会丢弃无法修复的数据)
redis-check-rdb --fix dump.rdb
2.5 RDB 的优缺点
优点:
-
RDB 是单一紧凑的二进制文件,非常适合做冷备份。每天生成一份 dump.rdb,压缩后存到对象存储或异地机房,出问题时直接拿它恢复。
-
恢复速度快。直接加载一个 RDB 文件,比逐条重放 AOF 日志快得多。
-
子进程写入,主进程几乎不受影响。
缺点:
-
两次快照之间的数据会丢失。如果 5 分钟保存一次,最坏情况就是丢 5 分钟的数据。
-
fork 子进程在内存大的时候耗时较长,会有短暂的阻塞。
3. AOF 日志持久化
3.1 AOF 是什么
AOF(Append Only File)记录的是每次写命令,追加到文件末尾。Redis 重启时,通过逐条重放 AOF 文件中的命令来恢复数据。
这就像 MySQL 的 binlog,记录了所有修改数据的操作。
3.2 AOF 的三种写入策略
AOF 的写入策略决定了性能和数据安全性之间的平衡。配置参数为 appendfsync:
# redis.conf
appendfsync always # 每个写命令都刷盘,最安全也最慢
appendfsync everysec # 每秒刷盘一次,折中方案(默认)
appendfsync no # 不主动刷盘,交给操作系统决定
三种策略对比:
| 策略 | 原理 | 数据安全性 | 性能 |
|---|---|---|---|
always | 每个写命令完成后立即调用 fsync 刷盘 | 最高,不丢数据 | 最差 |
everysec | 每秒执行一次 fsync,异步线程负责 | 最多丢 1 秒数据 | 折中 |
no | 不调用 fsync,由操作系统决定何时刷盘(通常 30s) | 最差,可能丢大量数据 | 最高 |
推荐使用 everysec,它是性能和安全性的最佳平衡。绝大部分业务场景下,丢 1 秒的数据是可以接受的。
3.3 AOF 重写(Rewrite)
AOF 文件会随着时间不断变大。比如对一个计数器反复执行 100 次 INCR,AOF 里就记录了 100 条命令,但恢复时只需要知道最终值就行。
AOF 重写就是把 AOF 文件压缩的过程:Redis 读取当前数据状态,生成一条条等价的 SET 命令写入新的 AOF 文件。
# 手动触发 AOF 重写
BGREWRITEAOF
重写过程同样通过子进程完成,利用 COW 机制,主进程几乎不受影响。重写期间的新写命令会同时写入旧 AOF 文件和一个重写缓冲区,子进程写完新文件后,主进程再把缓冲区里的增量命令追加到新文件末尾,最后用新文件替换旧文件。
自动触发的配置:
# 当 AOF 文件大小比上次重写后增长了 100% 时触发
auto-aof-rewrite-percentage 100
# AOF 文件最小达到 64MB 才考虑重写
auto-aof-rewrite-min-size 64mb
3.4 AOF 文件修复
# 检查 AOF 文件是否有损坏
redis-check-aof --fix appendonly.aof
# 查看 AOF 文件内容(可以看到具体的命令)
cat appendonly.aof
AOF 文件是文本格式(可以配置为混合格式),直接用 cat 就能看到里面的命令。排查问题时非常方便。
3.5 AOF 的优缺点
优点:
-
数据安全性高。
everysec策略下最多丢 1 秒数据,always下几乎不丢。 -
AOF 是文本文件(或混合文件),可读性强,便于排查问题。
-
自动重写机制可以控制文件大小。
缺点:
-
相同数据量下,AOF 文件通常比 RDB 大。
-
恢复速度比 RDB 慢,因为要逐条重放命令(混合持久化改善了这一点)。
-
频繁 fsync 会带来一定的性能开销。
4. 混合持久化(RDB-AOF Hybrid)
4.1 混合持久化解决什么问题
纯 AOF 的恢复速度慢,因为需要逐条执行命令。纯 RDB 的数据安全性差,因为两次快照之间有丢失窗口。
Redis 4.0 引入的混合持久化结合了两者的优点:
-
AOF 重写时,子进程把当前内存数据以 RDB 格式 写入 AOF 文件的开头。
-
重写期间的增量命令继续以 AOF 格式 追加到文件后面。
这样,AOF 文件的结构变成了:

恢复时,Redis 先加载前面的 RDB 部分(速度快),再重放后面的 AOF 增量命令(数据新)。既保证了恢复速度,又保证了数据安全性。
4.2 开启混合持久化
# redis.conf(Redis 4.0+ 默认开启)
aof-use-rdb-preamble yes
设置为 yes 后,BGREWRITEAOF 生成的 AOF 文件就是混合格式。不需要额外操作,AOF 重写会自动按混合格式生成。
5. RDB 和 AOF 的选择与组合
5.1 生产环境的配置建议
根据不同的场景需求,常见的组合策略有以下几种:
追求性能,可以接受少量数据丢失:
# 只开 RDB
save 900 1
save 300 10
save 60 10000
# 关闭 AOF
appendonly no
适用于缓存、排行榜等非核心数据。Redis 挂了就挂了,从数据库重新加载就行。
追求数据安全,可接受小幅性能下降:
# 同时开 RDB 和 AOF
save 900 1
save 300 10
save 60 10000
appendonly yes
appendfsync everysec
aof-use-rdb-preamble yes
适用于订单、支付等核心业务数据。绝大部分场景都推荐这套配置。
极致安全:
appendfsync always
每条写命令都刷盘,性能下降明显,一般只在金融、账务等对数据零容忍的场景使用。即便如此,也要先压测确认性能能否满足。
5.2 同时开启 RDB 和 AOF 时的恢复逻辑
Redis 重启时,如果同时存在 RDB 和 AOF 文件,优先使用 AOF 文件来恢复数据,因为 AOF 通常数据更完整。
如果只想要 RDB 的恢复速度但又需要 AOF 的数据安全,4.0 之后的混合持久化就是为此设计的。
5.3 数据恢复流程
# 1. 先把备份文件拷贝到 Redis 数据目录
cp dump.rdb /var/lib/redis/
cp appendonly.aof /var/lib/redis/
# 2. 检查文件完整性
redis-check-rdb dump.rdb
redis-check-aof --fix appendonly.aof
# 3. 启动 Redis
redis-server /etc/redis/redis.conf
启动后可以用 INFO Persistence 查看持久化状态:
redis-cli INFO Persistence
输出示例:
# Persistence
loading:0 # 0 表示没有在加载数据
rdb_last_save_time:1680000000 # 上次 RDB 保存的时间戳
rdb_last_bgsave_status:ok # 上次 BGSAVE 的状态
aof_enabled:1 # AOF 是否开启
aof_last_write_status:ok # 上次 AOF 写入的状态
aof_last_rewrite_time_sec:3 # 上次 AOF 重写耗时(秒)
6. 持久化相关的性能优化
6.1 fork 引起的阻塞
BGSAVE 和 BGREWRITEAOF 都需要 fork() 子进程。在内存大的实例上,fork 耗时可能达到秒级。
优化方向:
-
控制单实例内存大小,建议不超过 16GB。超过的话考虑拆分或使用 Redis Cluster。
-
避免在业务高峰期触发 BGSAVE 或重写。
-
对 Linux 内核参数进行调优,关闭 THP(透明大页):
# 关闭透明大页,减少 fork 时的内存复制开销
echo never > /sys/kernel/mm/transparent_hugepage/enabled
6.2 AOF 刷盘策略的选择
always 策略下每次写都 fsync,性能影响巨大。大多数场景用 everysec 就够了。如果 Redis 部署在 SSD 上,fsync 的开销会更低,安全性也更有保障。
6.3 多核 CPU 的利用
持久化过程中,主进程只用一个 CPU 核心处理请求,子进程也只用另一个核心写文件。如果有 4 核 CPU,其实只用了 2 核。所以持久化不会明显拖慢 Redis,但也别指望它能充分利用多核。
7. 运维实践中的注意事项
7.1 定期备份 RDB 文件
即使开了 AOF,也建议保留 RDB 备份,因为 RDB 恢复快。常见做法是:
# crontab 定时任务:每天凌晨 3 点备份
0 3 * * * cp /var/lib/redis/dump.rdb /backup/redis/dump_$(date +\%Y\%m\%d).rdb
备份文件最好压缩后上传到对象存储或异地服务器,防止本机磁盘损坏。
7.2 AOF 文件大小监控
设置监控告警,当 AOF 文件超过阈值(比如 10GB)时及时处理。AOF 文件过大通常是重写没有正常触发或重写太慢导致的。
7.3 主从架构下的持久化
很多人在主库上关掉持久化,让从库来做。这种做法有一定风险:
-
如果主从同时挂了(比如机房断电),数据全丢。
-
从库做持久化时,主库的数据可能还没同步过来,存在不一致。
更稳妥的做法是:主库开 AOF(everysec),从库开 RDB(用于备份)。这样既保证了主库的数据安全,又有从库的冷备。
7.4 避免持久化引起的性能抖动
-
设置
save参数时,避免在短时间内触发太多次 BGSAVE。 -
对于写密集场景,适当调高
auto-aof-rewrite-percentage,避免频繁重写。 -
监控
info Persistence中的rdb_last_bgsave_time_sec(上次 BGSAVE 耗时)和aof_last_rewrite_time_sec(上次重写耗时),如果耗时异常增长,说明内存数据量变大了,需要考虑拆分。
8. 总结
Redis 的持久化机制经历了三个阶段的演进:
-
纯 RDB 时代:简单,但丢数据多。
-
RDB + AOF 并存:安全了,但恢复慢。
-
混合持久化(4.0+):兼顾恢复速度和数据安全,是目前的最佳实践。
我个人在实际项目中的经验是:大多数场景用 RDB(冷备)+ AOF(混合持久化,everysec)这套组合就足够了。数据安全性有保障,恢复速度也快,性能开销在可接受范围内。
如果是纯缓存场景,数据可以从数据库重新加载,关掉持久化也没问题。但如果是存储了计数器、分布式锁、排行榜等不可再生数据,持久化就是必须的,宁可牺牲一点性能也要保证数据不丢。
排查持久化问题的第一手工具,关键命令:
# 随时查看持久化状态
INFO Persistence
# 检查 AOF 文件健康度
redis-check-aof --fix appendonly.aof
最后,如有改进之处欢迎指正,觉得有帮助的话不妨点赞收藏支持一下,感谢!

474

被折叠的 条评论
为什么被折叠?



