Redis 持久化 (Persistence) 是指将内存中的数据保存到磁盘,以防止在 Redis 服务器宕机时数据丢失。Redis 提供了两种主要的持久化方式:RDB (Redis Database) 快照和 AOF (Append Only File) 日志。理解这两种持久化机制的工作原理、优缺点以及如何选择和结合使用,对于确保 Redis 数据的可靠性和可用性至关重要。

核心思想:
Redis 持久化的目标是保障数据在意外停机后的恢复能力。RDB 侧重于某一时刻数据状态的完整性,而 AOF 侧重于每一操作的完整记录


一、Redis 持久化的必要性

Redis 作为一个高性能的内存数据库,其所有数据都存储在内存中。如果 Redis 服务器发生意外停机(如进程崩溃、服务器断电等),而没有进行持久化,那么内存中的所有数据都将丢失。这将导致严重的业务数据损失和可用性问题。

持久化的作用:

  1. 数据恢复:当 Redis 服务器重启时,可以通过加载磁盘上的持久化文件来恢复到最近一次保存的数据状态。
  2. 避免数据丢失:最大程度地减少因非预期故障导致的数据损失。
  3. 数据安全保障:为 Redis 提供类似传统关系型数据库的灾难恢复能力。

二、RDB 持久化 (Redis Database Snapshot)

RDB 持久化是将 Redis 在某个时间点的内存数据生成一份二进制快照文件(默认为 dump.rdb),保存到磁盘上。RDB 是 Redis 默认的持久化方式。

2.1 工作原理

RDB 的核心是 fork 子进程 来进行快照操作。

  1. 触发快照

    • 手动触发
      • SAVE 命令:在主进程中执行,会阻塞所有客户端请求,直到快照完成。生产环境强烈不推荐使用。
      • BGSAVE (Background SAVE) 命令:Redis 父进程 fork 出一个子进程,由子进程负责创建 RDB 文件,父进程继续处理客户端请求。这是推荐的 RDB 触发方式。
    • 自动触发:在 redis.conf 中配置 save 规则,例如 save 900 1 (900秒内有1次写入则触发)、save 300 10 (300秒内有10次写入则触发)。当满足任一条件时,Redis 会自动执行 BGSAVE
    • 其他触发
      • SHUTDOWN 命令正常关闭时,如果开启了 AOF 且未开启 RDB 自动保存,RDB 不会被触发。如果配置了 RDB 自动保存且上次保存失败,则在 SHUTDOWN 时会再次尝试 BGSAVE
      • 主从复制时,SAVE 命令可以用来同步数据。
  2. fork 子进程:当 BGSAVE 命令被执行时,Redis 主进程会 fork 一个子进程。fork 操作会复制一份父进程的页表,使得父子进程共享内存中的数据。

  3. 写时复制 (Copy-On-Write, CoW):当子进程生成 RDB 快照期间,如果主进程有写操作,Redis 使用 CoW 机制:

    • 如果主进程要修改某个共享的内存页,该页会先被复制一份,然后主进程在复制的页上进行修改,而子进程仍然读取原始的内存页。
    • 这样,子进程在整个快照期间读取的数据都是一致的,不会受到主进程修改数据的影响。
  4. 写入 RDB 文件:子进程遍历整个 Redis 数据库,将内存中的数据以紧凑的二进制格式写入到一个临时文件中。

  5. 替换 RDB 文件:当子进程完成写入后,会替换掉旧的 RDB 文件,并向父进程发送完成信号。

2.2 优点

  1. 紧凑性 (Compactness):RDB 文件是一个经过压缩的二进制文件,非常紧凑,占用磁盘空间小。
  2. 性能 (Performance)BGSAVE 方式,Redis 主进程不受阻塞,可以继续处理客户端请求。子进程在生成 RDB 文件时,主进程的写操作不会影响快照的一致性。
  3. 快速恢复 (Fast Recovery):由于 RDB 文件是数据的紧凑表示,加载速度比 AOF 快,恢复数据效率高。
  4. 利于备份 (Good for Backups):RDB 文件适合进行备份和灾难恢复,可以将其复制到异地存储。

2.3 缺点

  1. 数据丢失风险 (Data Loss Risk):RDB 是一种定期快照方式,如果在上次快照和服务器宕机之间发生数据修改,这些数据将会丢失。持久化频率越低,数据丢失的风险越高。
  2. fork 开销 (Fork Overhead)fork 子进程会消耗一定的内存和 CPU 资源。对于拥有超大内存的 Redis 实例,fork 过程可能会导致短暂的阻塞。
  3. 不适合实时持久化:无法做到数据的实时同步,不适合对数据完整性要求极高的场景。

三、AOF 持久化 (Append Only File)

AOF 持久化以日志的形式记录 Redis 接收到的每一个写操作命令。当 Redis 重启时,AOF 文件中的命令会被逐一重新执行,从而恢复数据。

3.1 工作原理

AOF 主要包括三个步骤:命令追加 (Append)文件写入 (Write)文件同步 (Sync)

  1. 命令追加 (Append)
    • Redis 接收到写命令后,会在响应客户端之前,将该命令以 Redis 协议格式追加到 AOF 缓冲区 (aof_buf) 的末尾。
  2. 文件写入 (Write)
    • Redis 会根据配置的同步策略,将 AOF 缓冲区的内容写入到 AOF 文件中。
  3. 文件同步 (Sync)/刷新 (Flush)
    • 为了确保数据真正落盘,操作系统会通过 fsync()fdatasync() 系统调用将文件写入缓存区的数据强制同步到磁盘。
    • Redis 提供了三种 AOF 同步策略(在 redis.conf 中配置 appendfsync):
      • appendfsync always:每个写命令都立即同步到磁盘。数据最安全,但性能最差。
      • appendfsync everysec:每秒同步一次。平衡了数据安全性和性能。推荐使用。
      • appendfsync no:完全由操作系统决定何时同步到磁盘。性能最好,但数据安全性最差。

3.2 AOF 重写 (AOF Rewrite)

随着 AOF 文件越来越大,恢复时间会变长,文件存储空间也会浪费。AOF 重写机制就是为了解决这个问题。

  • 目的:去除 AOF 文件中的冗余命令(例如对同一个键的多次修改,只保留最终状态的修改),将 AOF 文件压缩到最小。
  • 原理:Redis 创建一个子进程来生成一个新的 AOF 文件。这个子进程不会读取旧的 AOF 文件,而是遍历当前内存中的数据,将其转换为一系列写命令,写入到一个新的 AOF 临时文件中。
    • 在子进程进行 AOF 重写期间,主进程会继续处理客户端请求,并将新的写命令同时写入旧的 AOF 文件和 AOF 重写缓冲区。
    • 当子进程完成新的 AOF 文件生成后,主进程会将 AOF 重写缓冲区中的内容追加到新的 AOF 文件末尾,确保新旧数据一致。
    • 最后,用新的 AOF 文件替换旧的。
  • 触发
    • 手动触发BGREWRITEAOF 命令。
    • 自动触发:在 redis.conf 中配置 auto-aof-rewrite-percentage (增长度) 和 auto-aof-rewrite-min-size (最小触发大小)。

3.3 优点

  1. 数据安全性高 (Highest Data Safety):在 everysec 模式下,最多只会丢失 1 秒的数据。在 always 模式下,不会丢失数据。
  2. 日志友好 (Human Readable):AOF 文件是纯文本格式,可以通过打开文件查看 Redis 进行了哪些操作。
  3. 易于恢复 (Easy Recovery):AOF 文件中的命令可以直接被 Redis 再次执行以恢复数据。

3.4 缺点

  1. 文件大 (Larger File Size):AOF 文件通常比 RDB 文件大,特别是未经过重写时。
  2. 恢复速度慢 (Slower Recovery):Redis 需要逐条执行 AOF 文件中的命令来恢复数据,恢复速度可能比 RDB 慢,特别是 AOF 文件很大的情况下。
  3. 性能开销高 (Higher Performance Overhead)always 模式下每次写操作都会执行 fsync,对性能影响较大。everysec 模式下也会有略微的性能损失。
  4. 潜在的 Bug 风险:尽管 AOF 是基于命令的,但在极少数情况下,如果命令本身有 Bug 或 AOF 文件损坏,可能导致恢复失败。

四、如何选择持久化方式

特性 RDB (默认) AOF (可配置)
数据安全性 较高,但有数据丢失风险 (上次快照后修改的数据) 很高everysec 模式最多丢失1秒数据,always 模式不丢失数据
恢复速度 (直接加载二进制文件) 慢 (逐行执行命令)
文件大小 (紧凑的二进制格式) 通常较大 (日志格式,即使重写后也可能比 RDB 大)
性能影响 主进程在 BGSAVE 期间不阻塞,fork 有开销 always 模式阻塞,everysec 模式有额外 IO 开销
备份难度 容易,直接复制 RDB 文件 相对复杂,需要考虑重写机制
适用场景 对数据完整性要求不高,但要求恢复速度快的场景 对数据完整性要求高,允许略慢的恢复速度

4.1 单独使用 RDB

  • 如果在停机时丢失几分钟的数据可以接受。
  • 要求高性能和快速恢复。
  • 适合作为数据备份策略。

4.2 单独使用 AOF

  • 对数据完整性要求非常高,不能接受任何数据丢失。
  • 允许恢复时间稍长。

4.3 混合使用 RDB + AOF (推荐)

这是 Redis 4.0 以后引入的机制,也是目前最推荐的持久化方案。

  • 工作原理:AOF 文件由两部分组成:以 RDB 格式存储的快照数据和追加在其后的 AOF 日志。
  • 重写逻辑:当 AOF 重写时,会先以 RDB 方式将内存中的数据写入 AOF 文件的开头,然后将在这期间发生的所有命令记录在 AOF log 的后面,形成一个完整的 AOF 文件。
  • 优点
    • 恢复速度快:大部分数据从 RDB 部分加载,速度快。
    • 数据丢失少:可以像 AOF 一样实现每秒同步,最大程度地保证数据不丢失。
    • 文件更小:重写后 AOF 文件中 RDB 部分更紧凑。
  • 配置:在 redis.conf 中设置 aof-use-rdb-preamble yes

五、持久化配置与管理

以下是一些重要的 redis.conf 配置项:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# --- RDB 持久化配置 ---
# 快照保存条件
save 900 1 # 900秒内,如果至少有1个key被修改,则执行BGSAVE
save 300 10 # 300秒内,如果至少有10个key被修改,则执行BGSAVE
save 60 10000 # 60秒内,如果至少有10000个key被修改,则执行BGSAVE

# 当BGSAVE失败时,是否停止写入操作。
# 如果设置为yes,当BGSAVE快照失败,Redis将停止接受写操作。直到BGSAVE成功后,才恢复写操作,主要目的在于避免数据丢失。
stop-writes-on-bgsave-error yes

# 是否压缩RDB文件。如果禁用,RDB文件会更大,但保存和加载速度会更快。
rdbcompression yes

# RDB文件校验。crc64校验会增加10%的性能开销,但能保证文件完整性。
rdbchecksum yes

# RDB文件名称
dbfilename dump.rdb

# RDB文件保存路径
dir ./

# --- AOF 持久化配置 ---
# 是否开启AOF
appendonly no # 默认为no,设置为yes开启AOF

# AOF文件名
appendfilename "appendonly.aof"

# AOF同步策略
# no: 不进行fsync,由操作系统控制。最快,最不安全。
# always: 每执行一个写命令就执行一次fsync。最慢,最安全。
# everysec: 每秒执行一次fsync。推荐,平衡了性能和数据安全。
appendfsync everysec

# AOF重写最小增量
auto-aof-rewrite-percentage 100 # 当AOF文件大小增加到上次重写大小的百分比时触发重写

# AOF重写最小大小
auto-aof-rewrite-min-size 64mb # AOF文件小于此值时,即使达到百分比也不会重写

# Redis 4.0 引入的混合持久化模式
# yes: 开启混合持久化,AOF文件以RDB格式开头,后面追加AOF Log。
# no: 禁用混合持久化,AOF文件完全是命令日志。
aof-use-rdb-preamble yes

六、总结

Redis 的 RDB 和 AOF 持久化机制各有优势和劣势。RDB 提供紧凑、快速恢复的快照,但可能有数据丢失风险;AOF 提供更高的数据安全性,但文件可能更大且恢复速度稍慢。

在生产环境中,最推荐的策略是同时开启 RDB 和 AOF,并且启用 Redis 4.0 引入的混合持久化模式 (aof-use-rdb-preamble yes)。这样可以在保证数据最大程度安全的同时,兼顾恢复速度,为 Redis 实例提供全面的数据保障。同时,配合定期的 RDB 备份到异地存储,可以构建一个健壮的 Redis 数据持久化和灾难恢复方案。