你们线上的Redis是开启了AOF、RDB还是混合持久化?基于什么样的业务考量做出的这个决策?
在实际的生产环境中,作为架构/后端负责人的视角,我们并没有采用“一刀切”的策略,而是根据不同的业务场景和数据重要程度,采取了分类治理的持久化策略。
但在绝大多数核心业务集群中,我们默认开启的是混合持久化(RDB + AOF)(Redis 4.0 及以上版本支持)。
以下是具体的业务考量和不同场景下的决策全景:
一、 核心业务集群:采用“混合持久化”
策略: 开启 AOF,并配置 aof-use-rdb-preamble yes(开启混合持久化),AOF 刷盘策略设为 everysec(每秒)。
业务考量:
- 追求“数据安全性”与“恢复速度”的完美折中:
- 纯 RDB 丢失数据太多(可能丢失几分钟到几十分钟的数据),业务无法接受。
- 纯 AOF 数据虽然完整,但文件体积大,如果发生宕机重启,几十 GB 的 AOF 文件重放需要极长的时间(可能长达数十分钟)。在核心业务中,Redis 宕机引发的缓存雪崩如果持续十分钟,底层数据库(如 MySQL)早就被打挂了。
- 混合持久化的优势: AOF 重写时,将当前数据以 RDB 的格式写入文件开头,之后的增量数据追加为 AOF 命令。这样重启时,先快速加载 RDB,再重放少量的 AOF 命令,既保证了重启速度(秒级/分钟级恢复),又保证了最多只丢失 1 秒的数据。
- 防范灾难性故障(兜底): 核心电商交易状态、分布式锁、高频变化的业务计数器,这些数据如果大面积丢失会导致业务逻辑混乱,混合持久化提供了最好的兜底。
二、 纯缓存业务集群:关闭持久化 或 仅 RDB
策略: 完全关闭 AOF,仅保留低频率的 RDB(例如 save 3600 1,一小时一次)或者干脆完全关闭持久化。
业务考量:
- 性能与 I/O 的极致压榨: 比如资讯页缓存、商品详情页的基础信息缓存。这些数据在 MySQL 中有完整的全量数据。开启 AOF 会带来不必要的磁盘 I/O 开销,影响 Redis 的吞吐量。
- 容灾策略依赖“预热”而非“恢复”: 这类 Redis 如果宕机,我们的处理方案通常是直接拉起新的空实例,然后通过业务层的异步缓存预热系统或者请求回源加持互斥锁(防击穿)来重新加载数据,而不是让 Redis 慢慢从磁盘读数据。
- 节约成本: 关闭持久化可以避免
bgsave或bgrewriteaof时产生的 fork 操作,减少对 CPU 和内存(Copy-On-Write)的占用,从而可以在单机上部署更高密度的实例。
三、 强状态/类数据库集群:AOF + RDB 备份 + 主从架构定制
策略: 开启 AOF(everysec),关闭自动 RDB。但通过定时任务(如 Crontab),每天凌晨低峰期在从节点(Slave)执行 bgsave,并将 RDB 文件推送到冷备对象存储(如 OSS/S3)中。
业务考量:
- 充当内存数据库使用: 比如一些高频的排行榜、用户在线状态、风控防刷计数。这些数据一旦丢失且无法从 MySQL 恢复,业务将面临资损或客诉。
- 主从职责分离(性能与安全的隔离):
- 主节点(Master): 承担高并发读写,为了避免 AOF 重写或 bgsave 带来的阻塞和毛刺(尤其是在 SSD 性能瓶颈时),有时我们会在主节点关闭持久化。
- 从节点(Slave): 不对外提供读写,专职负责开启混合持久化和定时生成 RDB 快照。
- 注意点: 如果采用主节点关闭持久化的方案,必须关闭主节点的自动拉起(重启)功能。否则主节点宕机后自动空载重启,会将从节点的数据也同步清空,造成灾难性后果。应该由 Sentinel/Cluster 选出新主节点后,再人工介入原主节点。
总结:我们在线上做决策的核心准则
在做出这些决策时,我们不仅仅是看 Redis 的配置文件,而是结合了整个系统架构进行考量:
- SLA 要求: 业务能容忍丢失多少数据?能容忍多长时间的恢复期?(混合持久化是 90% 场景的最优解)。
- 物理机资源: 只要开启持久化,就必须为机器预留至少 30% - 40% 的空闲内存,以应对
bgsave/bgrewriteaof时的写时复制(COW)导致的内存上涨,防止 OOM。 - 磁盘 I/O 干扰: 如果开启 AOF,我们会配置
no-appendfsync-on-rewrite yes。即在进行 AOF 重写时,暂停 AOF 刷盘,容忍少量数据丢失的风险,来换取 Redis 主线程不被磁盘 I/O 阻塞。