Redis作为主流的内存数据库,所有键值对默认存放在内存中,一旦进程退出或服务器断电,未保存的数据便会彻底消失。为解决服务重启后数据不丢失的问题,Redis设计了多种持久化方案,核心思路是把内存状态或写操作记录定期或实时写到磁盘文件里。本文围绕RDB、AOF以及混合持久化展开,说明它们的工作原理、配置方式与适用场景。

一、RDB快照持久化
RDB(Redis Database)是Redis最早的持久化方式,它通过创建某个时间点的内存数据快照,将全量数据以紧凑的二进制格式写入磁盘文件(默认名为dump.rdb)。当Redis重新启动时,只要加载该文件即可恢复此前的内存状态。RDB的生成过程依赖操作系统fork机制:父进程调用fork分出子进程,子进程负责遍历内存并写文件,父进程继续对外提供服务,因此正常情况对线上读写影响较小。
触发RDB的方式分为手动与自动两类。手动执行save命令会阻塞主线程直到完成,生产环境基本不用;更常用的是bgsave,它后台异步落盘。自动触发则在配置文件中通过save 秒数 改动次数规则定义,例如save 900 1表示900秒内有至少1次修改就触发bgsave。下面是一段典型的redis.conf片段:
# RDB自动保存规则 save 900 1 save 300 10 save 60 10000 # RDB文件名与目录 dbfilename dump.rdb dir /var/lib/redis
RDB的优点非常明显:文件体积小、恢复速度快,适合做定时备份和主从全量同步的源头。但它属于定点快照,若上一次bgsave后发生崩溃,中间写入的数据就会丢失,一般最多可能丢掉几分钟的业务记录。此外,当数据量很大时,fork操作本身可能带来毫秒到秒级的延迟尖刺,需要结合内存与CPU情况评估。
二、AOF日志持久化
AOF(Append Only File)以日志形式记录每一个写命令,重启时重新执行这些命令来重建数据。与RDB不同,AOF更关注过程而非结果,因此数据安全性更高。Redis把命令先追加到内存中的AOF缓冲区,再根据配置的刷盘策略同步到磁盘。
刷盘策略由appendfsync控制,可选值有always、everysec、no。always代表每条命令都落盘,最安全但性能最差;everysec每秒批量刷一次,最多丢失一秒数据,是官方推荐默认值;no交给操作系统调度,丢失量不可控。随着运行时间变长,AOF文件会不断膨胀,Redis提供重写机制,在后台生成等价的最小命令集来压缩文件。相关配置如下:
# 开启AOF appendonly yes # 每秒刷盘 appendfsync everysec # 重写触发条件 auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb
AOF保障了更高的持久化完整性,尤其对交易、会话等不能丢数据的场景更友好。代价是文件通常比RDB大,且恢复时要逐条重放命令,启动较慢。如果业务可以接受秒级丢失,everysec在性能与可靠之间取得了不错平衡。实际运维中,AOF重写期间也会消耗IO与CPU,建议放在低峰期自动或手动触发。
三、混合持久化与选型建议
Redis 4.0之后引入了混合持久化(aof-use-rdb-preamble),它在AOF重写时先以RDB格式写入全量快照,再把重写期间的增量命令以AOF格式附加在后。这样既保留了RDB快速加载的优势,又通过尾部AOF补齐了最近数据,重启时先读RDB再补命令,兼顾速度与安全性。
对于大多数线上服务,推荐开启AOF并配合混合持久化,同时保留RDB作为冷备。如果单纯做缓存且允许丢失,可只开RDB甚至关闭持久化以提升吞吐。下面的配置展示了混合模式的关键项:
appendonly yes appendfsync everysec aof-use-rdb-preamble yes save 300 10
在容器化或云环境里,还应把持久化目录挂载到独立卷,避免容器销毁连带数据消失。监控方面,可关注latest_fork_usec、aof_current_size等指标,及时发现fork阻塞或文件异常增长。通过合理组合RDB与AOF,就能在重启后把数据丢失控制在业务可接受的范围内。
四、常见误区与排查
不少团队误以为开了AOF就绝对不丢数据,实际上若使用appendfsync no或磁盘故障,仍可能丢失。还有人把RDB的save规则设得过密,导致fork频繁影响响应。遇到启动加载慢时,可检查是否AOF未开混合导致全命令重放。
当怀疑持久化异常,先用redis-cli info persistence查看aof_enabled、rdb_last_bgsave_status等字段。必要时手动执行bgrewriteaof与bgsave观察日志,确认子进程成功退出且无磁盘写满问题。理清机制再调参,才能让Redis在重启后稳稳找回数据。