← 返回文章

Redis 持久化

发布于 2026/10/19

1. 完整回答

Redis 持久化是指将内存中的数据保存到磁盘,让 Redis 在重启或者发生故障后能够恢复数据,降低数据丢失的风险。

Redis 主要提供两种持久化机制:RDB 和 AOF。

RDB 是快照持久化,会在指定条件下,将某一时刻的内存数据保存成二进制文件。通常通过 BGSAVE 创建子进程执行持久化,主进程继续处理请求,并利用写时复制机制保证快照的数据一致性。它的优点是文件紧凑、恢复速度快,适合数据备份;缺点是两次快照之间发生故障,可能丢失这段时间的数据。

AOF 是追加日志持久化,会记录执行过的写命令,Redis 重启时通过加载并重放日志恢复数据。AOF 支持不同的刷盘策略,常用的是 everysec,也就是每秒进行一次刷盘,通常只会丢失最近约一秒的数据,但这并非绝对保证。

由于 AOF 会不断增长,Redis 还提供了 AOF 重写机制,根据当前内存中的数据生成更精简的持久化文件,减少磁盘占用。

另外,Redis 支持混合持久化,使用 RDB 格式保存基础数据,再通过增量 AOF 记录后续修改,从而兼顾恢复速度和数据安全性。

实际项目中,如果 Redis 只用于可重建的缓存,可以根据成本和恢复要求选择 RDB,甚至关闭持久化。如果数据恢复要求较高,通常会结合 RDB 备份、AOF everysec 和混合持久化,同时配合主从复制及异地备份。

2. 核心原理与关键概念

2.1 RDB 持久化原理

核心流程:

触发快照 → 创建子进程 → 写时复制 → 生成 RDB 文件 → 替换旧文件

  1. 触发快照:达到配置的保存条件,或者执行 BGSAVE。

  2. 创建子进程:主进程通过 fork 创建子进程,子进程负责生成快照,主进程继续处理请求。

  3. 写时复制(COW):父子进程最初共享内存物理页。主进程修改共享页面时,操作系统复制对应页面,使子进程能够保留快照时刻的数据视图。

  4. 生成文件:子进程将数据写入临时 RDB 文件,完成后替换旧文件。

关键特点: RDB 保存的是某一时刻的数据状态,快照过程通常不会持续阻塞主进程,但 fork 本身可能造成短暂阻塞,写入密集时还会产生额外内存开销。

2.2 AOF 持久化原理

核心流程:

执行写命令 → 追加 AOF 缓冲区 → write 写入操作系统缓存 → 按策略 fsync 刷盘 → 重启加载日志

  1. 执行命令:Redis 先执行写命令,再将需要持久化的操作记录到 AOF 缓冲区。

  2. 写入文件:通过 write 将日志写入操作系统文件缓存。

  3. 同步磁盘:根据 appendfsync 策略,决定什么时候调用 fsync,将数据同步到持久化存储。

  4. 恢复数据:Redis 重启时加载 AOF,按照记录的顺序恢复数据库状态。

关键特点: AOF 的数据安全性主要取决于刷盘策略。写入操作系统缓存,并不等于已经完成磁盘持久化。

2.3 AOF 重写原理

核心流程(Redis 7.0 及之后):

触发重写 → fork 子进程 → 生成新的基础文件(BASE)→ 主进程记录增量文件(INCR)→ 原子切换清单(manifest)→ 清理旧文件

重写过程直接根据当前内存数据生成新的基础文件,不需要逐条读取旧 AOF 日志。

例如,一个计数器执行了 100 次 INCR,重写后可以使用更精简的命令表示当前结果,减少冗余日志。

Redis 7.0 开始采用多段 AOF 机制:

  • BASE:保存重写时的基础数据,可以采用 RDB 或 AOF 格式。

  • INCR:记录基础数据生成后发生的增量写操作。

  • manifest:管理有效的基础文件和增量文件。

重写期间主进程持续接收写请求,完成后通过原子更新 manifest 切换文件集合,避免遗漏增量数据。

2.4 混合持久化原理

混合持久化可以通过 aof-use-rdb-preamble yes 启用。

核心流程:

AOF 重写 → 使用 RDB 格式生成 BASE → 后续写操作记录到 INCR → 重启加载 BASE → 加载并重放 INCR

这样恢复时可以先快速加载 RDB 格式的基础数据,再恢复增量写入,减少纯 AOF 命令重放的开销。

需要注意,混合持久化与同时开启 RDB、AOF 是两个不同的概念:前者是 AOF 内部采用混合格式,后者是两套持久化机制同时工作。

2.5 关键概念

概念 作用
fork 创建子进程执行后台持久化任务
COW(写时复制) 共享未修改的内存页,保证快照视图一致,并减少初始内存复制
write 将 AOF 数据写入操作系统文件缓存
fsync 请求操作系统将文件数据同步到持久化存储
BGSAVE 后台生成 RDB 快照
BGREWRITEAOF 后台重写 AOF,压缩冗余写操作

3. 高频面试追问

3.1 RDB 的 SAVE 和 BGSAVE 有什么区别?

核心区别是 SAVE 会同步阻塞 Redis,BGSAVE 通过子进程完成快照生成。

SAVE 直接在主进程执行数据保存,期间无法正常处理其他客户端请求,因此生产环境通常不使用。

BGSAVE 通过 fork 创建子进程,由子进程写入 RDB 文件,主进程可以继续处理请求。

不过,BGSAVE 也会有短暂阻塞,因为 fork 需要创建子进程并处理相关内存页表。数据集越大,创建子进程的开销通常越明显。

继续追问:RDB 自动触发条件是什么?

可以通过 save 配置,例如 save 60 1000,表示在 60 秒内至少发生 1000 次数据修改时,满足一次自动快照的触发条件。Redis 会在运行过程中检查条件,满足后尝试执行后台保存。

3.2 为什么 RDB 需要写时复制?会有什么问题?

写时复制主要用于在保证快照一致性的同时,减少创建子进程时的内存复制开销。

执行 fork 后,父子进程最初共享物理内存页。子进程读取快照时的数据,主进程继续处理写请求。

当主进程修改共享页面时,操作系统复制对应内存页,主进程修改新页面,子进程仍然读取旧页面。

这样子进程就能保存快照创建时的数据状态。

它的主要问题是,持久化期间写请求越密集,可能触发的内存页复制越多。如果内存不足,可能导致 fork 失败、系统内存压力增大,甚至出现进程被终止的问题。

因此,生产环境需要预留内存余量,并关注 fork 延迟和 COW 内存使用情况。

3.3 为什么 AOF 在执行写命令之后才记录日志?

因为 Redis 可以先确认命令执行成功,再记录实际生效的写操作,减少日志记录阶段的额外校验。

正常情况下,命令执行完成后,Redis 才将对应操作追加到 AOF 缓冲区。

这种方式有两个特点:

  1. 日志记录阶段不需要重新验证命令是否有效。

  2. 命令执行和日志持久化之间存在时间窗口,如果发生异常退出,尚未持久化的修改可能丢失。

另外,AOF 追加和文件写入也会消耗资源,磁盘繁忙时可能影响后续命令处理。

3.4 AOF 的三种刷盘策略有什么区别?

核心区别是数据安全性、写入性能以及可能丢失的数据范围。

策略 刷盘方式 特点
always 每批写入后同步刷盘 安全性最高,写入延迟较大
everysec 通常每秒由后台线程刷盘一次 兼顾性能与安全性,常用方案
no 由操作系统决定刷盘时机 Redis 不主动同步,丢失窗口不可控

实际项目中,everysec 通常更合适,因为它通过后台刷盘降低主线程等待磁盘的开销,正常情况下故障可能损失最近约一秒的数据。

需要注意,磁盘持续繁忙或刷盘延迟时,数据丢失窗口可能扩大,因此不能把一秒理解成严格上限。

3.5 AOF 为什么需要重写?重写会影响正常写入吗?

AOF 重写用于消除历史冗余操作,控制文件大小;重写期间 Redis 通常可以继续处理写请求。

例如,一个 Key 被连续修改 100 次,恢复当前状态时,只需要最终有效的数据。

AOF 重写会根据当前内存中的数据生成精简的持久化内容,避免无限保存重复操作。

Redis 7.0 及之后,重写期间由子进程生成新的 BASE,主进程继续将新写入记录到 INCR 文件。

重写完成后,Redis 通过 manifest 原子切换有效文件集合。

这样即使重写失败,旧的有效文件和已记录的增量仍然可以用于恢复。

不过,重写涉及 fork、COW 和大量磁盘 I/O,仍然可能造成延迟升高。

3.6 Redis 同时开启 RDB 和 AOF,重启时优先加载哪个?

正常情况下优先加载 AOF,因为 AOF 通常包含比最近一次 RDB 快照更完整的数据。

RDB 只保存快照时刻的数据,而 AOF 会持续记录后续写操作。

例如,RDB 在 10:00 完成快照,Redis 在 10:05 发生故障。如果这段时间的 AOF 已成功持久化,加载 AOF 就能恢复更多数据。

如果使用混合持久化,Redis 会先加载 AOF 中 RDB 格式的基础数据,再恢复增量 AOF。

因此,同时开启 RDB 和 AOF,不代表 Redis 启动时会先加载独立的 RDB 文件,再追加独立 AOF 文件。

3.7 Redis 持久化应该怎么选择?

主要根据允许丢失多少数据、恢复速度要求和性能成本来选择。

如果 Redis 主要承担热点数据缓存,数据可以从数据库重新构建,那么可以使用 RDB,或者根据需求关闭持久化。

如果 Redis 保存会话状态、任务进度等需要尽量保留的数据,可以使用 AOF everysec,并结合 RDB 快照备份。

如果数据量较大,同时希望减少 AOF 恢复时的命令重放成本,可以考虑开启混合持久化。

实际方案还需要结合主从复制、异地备份以及故障恢复演练。Redis 持久化只能降低数据丢失风险,无法单独提供完整的高可用和灾难恢复能力。

3.8 Redis 持久化为什么可能导致性能下降?

主要原因包括 fork 阻塞、COW 内存开销和磁盘 I/O 竞争。

首先,RDB 快照和 AOF 重写都可能执行 fork,数据集较大时会引起主线程短暂阻塞。

其次,后台持久化期间,如果大量修改内存数据,COW 会增加额外内存消耗。

最后,RDB 文件生成、AOF 写入和刷盘都会产生磁盘 I/O。当磁盘繁忙时,写入延迟可能传递到 Redis 主线程。

排查时可以通过 INFO persistence 查看后台任务状态、最近持久化结果和 COW 内存大小,再配合 INFO stats 中的 latest_fork_usec、LATENCY 诊断以及系统磁盘监控定位问题。

优化方式包括预留内存、合理控制持久化频率、使用性能合适的磁盘,以及避免多个实例同时进行大量持久化操作。

3.9 AOF 文件损坏或者磁盘写满怎么办?

需要先确认持久化文件状态,保留原始数据,再决定恢复方式。

如果 AOF 只是末尾存在未写完整的命令,在允许截断加载的配置下,Redis 可以丢弃不完整的尾部记录并继续恢复。

如果文件中间发生损坏,可能导致 Redis 启动失败。这时需要先备份原始文件,再使用 redis-check-aof 检查和修复,并评估可能损失的数据。

如果是磁盘空间不足,需要先恢复可用空间,再检查 AOF 写入状态、重写状态和持久化日志。

生产环境还应监控 aof_last_write_status、aof_last_bgrewrite_status 等指标,及时发现磁盘和持久化异常。

3.10 开启 AOF 就能保证 Redis 数据完全不丢失吗?

不能。AOF 可以提高持久性,但数据安全性仍取决于刷盘策略以及故障类型。

使用 everysec 时,Redis 可能丢失尚未完成刷盘的数据。

使用 always 时,Redis 会在确认相应写入前执行磁盘同步,能够显著降低单机异常退出导致的数据丢失风险,但磁盘损坏、存储故障和人为误操作仍可能造成数据丢失。

此外,Redis 主从复制通常是异步的,主节点故障切换时也可能丢失尚未复制到新主节点的写入。

因此,重要数据通常需要结合持久化、复制、独立备份和业务层的可靠性机制。

4. 易混淆概念对比

4.1 RDB、AOF 与混合持久化

对比项 RDB AOF 混合持久化
核心机制 保存数据快照 记录写操作 RDB 格式基础数据 + 增量 AOF
数据安全性 取决于快照间隔 取决于刷盘策略 取决于 AOF 刷盘策略
恢复速度 通常较快 纯日志恢复通常较慢 通常比纯日志恢复更快
文件体积 通常较小 通常较大 通常比纯日志更紧凑
典型场景 数据备份 降低数据丢失风险 兼顾恢复效率和数据安全

4.2 其他容易混淆的概念

概念 A 概念 B 核心区别
SAVE BGSAVE 前者同步执行并阻塞请求;后者通过子进程后台保存
AOF 追加 AOF 重写 前者持续记录写操作;后者根据当前数据压缩历史冗余
write fsync 前者通常先写入操作系统缓存;后者负责请求同步到持久化存储
同时开启 RDB、AOF 混合持久化 前者同时使用两套机制;后者在 AOF 内部采用 RDB 格式基础数据和增量日志
持久化 主从复制 前者解决故障后的数据恢复问题;后者提供数据副本并支持高可用架构

5. 总结

Redis 持久化主要用于将内存数据保存到磁盘,降低服务重启或者故障造成的数据丢失风险。核心机制包括 RDB、AOF 和混合持久化。RDB 通过后台快照保存某一时刻的数据,文件紧凑、恢复速度快,但可能丢失快照之后的修改;AOF 通过记录写操作恢复数据,可以利用 everysec 刷盘策略在性能和安全性之间取得平衡,并通过后台重写控制文件大小;混合持久化则利用 RDB 格式的基础数据和增量 AOF 提升恢复效率。实际项目中通常根据数据丢失容忍度和恢复时间要求选择方案,同时结合复制和备份,因为单靠持久化无法保证数据绝对安全。