Redis 提供了两种主要的持久化机制,用于将内存中的数据保存到磁盘,以防止服务器重启或故障导致数据丢失。这两种机制分别是 RDB(Redis Database)和 AOF(Append Only File)。
1. RDB 持久化
RDB 是 Redis 默认的持久化方式,它通过创建内存中数据的快照来实现持久化。
2.RDB 持久化的触发方式
1. 自动触发(配置文件方式)
这是最常用的方式,通过在 Redis 配置文件(redis.conf
)中设置触发条件,当满足条件时自动执行 RDB 持久化。
配置格式:
save <seconds> <changes>
表示在 seconds
秒内发生了至少 changes
次数据修改时,触发 RDB 快照。
默认配置:
save 900 1 # 900秒内有至少1个键被修改
save 300 10 # 300秒内有至少10个键被修改
save 60 10000 # 60秒内有至少10000个键被修改
2. 手动触发
可以通过 Redis 命令手动触发 RDB 持久化:
SAVE
命令:
执行该命令时,Redis 主进程会直接进行 RDB 持久化操作,期间会阻塞所有客户端请求,直到 RDB 完成。127.0.0.1:6379> SAVE OK
适合在低峰期或维护时使用。
BGSAVE
命令:
执行该命令时,Redis 会 fork 一个子进程来进行 RDB 持久化,主进程继续处理客户端请求,不会阻塞服务。127.0.0.1:6379> BGSAVE Background saving started
这是更常用的手动触发方式。
注意:
执行flushall也会清空rdb文件
1.fork
在 Redis 中,
fork
是一个非常关键的系统调用(由操作系统提供),用于创建一个与当前进程(父进程)几乎完全相同的新进程(子进程)。当 Redis 执行
BGSAVE
命令时,会通过fork
操作创建一个子进程,这个子进程会复制父进程的内存数据,然后负责将数据写入 RDB 文件。
fork
的特点:
内存共享机制:
- 在 Linux 系统中,
fork
采用 写时复制(Copy-On-Write) 技术,初始时子进程并不会真正复制父进程的全部内存数据,而是共享同一块内存。- 只有当父进程或子进程修改数据时,才会复制被修改的部分数据,这样可以大大节省内存和提高效率。
对 Redis 的意义:
- 主进程(父进程)可以继续处理客户端请求,不会被阻塞。
- 子进程专注于将数据写入磁盘生成 RDB 文件,完成后会自动退出。
可能的影响:
fork
操作本身会短暂阻塞主进程(阻塞时间与内存大小相关)。- 如果数据集非常大,
fork
可能会导致 Redis 出现短暂的响应延迟。简单来说,
fork
让 Redis 能够在不中断服务的情况下完成 RDB 持久化,是实现后台异步操作的核心机制。
2.写时拷贝
写时拷贝的核心原理:
当一个进程(父进程)通过
fork
创建新进程(子进程)时,不会立即复制父进程的全部内存数据,而是让父子进程共享同一块内存空间。只有当其中一方(父进程或子进程)修改数据时,才会复制被修改的那部分内存页,确保双方的数据独立性。
3.rdb文件
redis的工作目录
后续redis服务器重新启动,就会尝试加载这个rdb文件,如果发现格式错误,就可能会加载数据失败,rdb文件虽然咱们不去主动动他,但是也可能会出现一些意外问题,一旦通过一些操作(比如网络传输)引起这个文件被破坏,此时redis服务器就无法启动
redis官方提供了rdb文件检查工具
注意:
如果redis异常退出(如服务器崩溃,kill-9),此时redis服务器来不及生成rdb,内存中尚未保存到快照中的数据,就会随重启而丢失
当rdb文件错误时,启动redis加上rdb文件来预警
3. 其他触发场景
服务器关闭时:当执行
SHUTDOWN
命令关闭 Redis 服务器时,Redis 会自动执行一次SAVE
命令,生成 RDB 文件后再关闭,确保数据不丢失。主从复制时:当从节点连接主节点时,主节点会自动执行一次
BGSAVE
生成 RDB 文件,并发送给从节点,用于数据同步。
工作原理:
- Redis 在指定的时间间隔内,将内存中的数据集快照写入磁盘的二进制文件(默认文件名是
dump.rdb
) - 当 Redis 重启时,会读取这个文件恢复数据
配置方式(在 redis.conf 中):
# 900秒内有至少1个键被修改,则触发快照
save 900 1
# 300秒内有至少10个键被修改,则触发快照
save 300 10
# 60秒内有至少10000个键被修改,则触发快照
save 60 10000
#关闭自动生成快照
save ""
优点:
- 生成的 RDB 文件是紧凑的二进制文件,适合用于备份和灾难恢复
- 恢复大数据集时速度比 AOF 快
- 对 Redis 性能影响较小,因为 fork 子进程进行持久化操作
缺点:
- 可能会丢失最后一次快照之后的数据
- 如果数据集很大,fork 过程可能会阻塞 Redis 服务器一段时间
3. AOF 持久化
AOF 持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来恢复数据。
工作原理:
- 每当执行一个改变数据集的命令时,Redis 就会将该命令追加到 AOF 文件的末尾
- 当 Redis 重启时,会重新执行 AOF 文件中的所有命令以恢复数据
配置方式(在 redis.conf 中):
# 开启 AOF 持久化
appendonly yes
# AOF 文件名
appendfilename "appendonly.aof"# AOF 同步策略
# appendfsync always # 每次有写操作就立即同步到磁盘,最慢但最安全
appendfsync everysec # 每秒同步一次,平衡性能和安全性(默认)
# appendfsync no # 由操作系统决定何时同步,最快但最不安全
AOF是否会影响redis性能
AOF缓冲区刷新策略
1. always(每写命令都同步)
- 策略描述:每当有新的写命令追加到 AOF 文件时,Redis 就会立即调用系统的
fsync
函数,将 AOF 缓冲区中的数据强制写入磁盘 。- 优点:数据安全性最高,因为一旦写入成功,数据就已经持久化到磁盘,即使发生系统崩溃、断电等异常情况,最多只会丢失刚刚执行但还没来得及写入 AOF 文件的那一个写命令的数据。
- 缺点:性能开销较大,频繁的磁盘 I/O 操作会降低 Redis 的写入性能,因为每次写操作都需要等待磁盘写入完成。
2. everysec(每秒同步)
- 策略描述:Redis 会每秒调用一次
fsync
函数,将 AOF 缓冲区中的数据写入磁盘。- 优点:兼顾了数据安全性和性能。在大多数情况下,即使发生系统崩溃,最多只会丢失 1 秒内的数据 ,同时又避免了过于频繁的磁盘 I/O 操作,对 Redis 的性能影响相对较小。
- 缺点:在极端情况下,比如系统崩溃时刚好距离上次
fsync
超过 1 秒,可能会丢失这 1 秒内的写命令数据。3. no(由操作系统决定同步时机)
- 策略描述:Redis 不主动调用
fsync
函数,而是将数据写入 AOF 缓冲区后,由操作系统来决定何时将缓冲区的数据真正写入磁盘。- 优点:对 Redis 性能影响最小,因为减少了 Redis 对磁盘 I/O 操作的干预,写操作只是简单地追加到缓冲区,不需要等待磁盘写入。
- 缺点:数据安全性最低,因为数据停留在缓冲区的时间不确定,一旦系统崩溃,缓冲区中未写入磁盘的数据都会丢失,可能会丢失大量数据。
在实际应用中,
everysec
是最常用的 AOF 刷新策略,它在数据安全性和性能之间找到了一个较好的平衡点。 可以在 Redis 的配置文件(redis.conf
)中通过appendfsync
配置项来设置 AOF 刷新策略,例如:plaintext
appendfsync always # 或者 appendfsync everysec # 或者 appendfsync no
也可以在 Redis 运行时,通过
CONFIG SET appendfsync <策略值>
命令动态修改 AOF 刷新策略。
AOF重写机制
AOF(Append Only File)重写机制是 Redis 中用于优化 AOF 文件大小的一种重要机制。随着 Redis 不断执行写命令并将其追加到 AOF 文件中,AOF 文件会越来越大,不仅占用过多磁盘空间,还会导致 Redis 在重启时,重放 AOF 文件中的命令耗时过长,影响恢复速度 。AOF 重写机制主要做了以下几件事:
1. 原理
AOF 重写是指 Redis 会读取当前数据库中的所有键值对,然后根据这些键值对重新构建出能够恢复当前数据库状态的最小命令集合,再将这些命令写入一个新的 AOF 文件,而不是简单地将原 AOF 文件中的命令进行压缩。
举个例子,假设先后执行了三条命令:
SET key1 value1 APPEND key1 value2 APPEND key1 value3
在 AOF 文件中会依次记录这三条命令。但通过 AOF 重写,Redis 会直接生成
SET key1 value1value2value3
这一条命令,达到同样的效果,却极大减少了命令数量。2. 触发方式
- 手动触发:可以通过
BGREWRITEAOF
命令手动触发 AOF 重写。执行该命令后,Redis 会在后台(fork 一个子进程)进行 AOF 重写操作,不会阻塞主线程,保证 Redis 的正常服务。- 自动触发:Redis 会根据配置文件中的相关参数自动触发 AOF 重写。主要涉及两个参数:
auto-aof-rewrite-percentage
:指定 AOF 文件大小相较于上次重写后增长的百分比。默认值为 100,表示如果 AOF 文件大小比上次重写后增大了一倍(100%),就可能触发 AOF 重写。auto-aof-rewrite-min-size
:指定触发 AOF 重写的最小 AOF 文件大小。默认值为 64MB,即只有当 AOF 文件大小大于等于 64MB,且满足auto-aof-rewrite-percentage
设定的增长条件时,才会触发 AOF 重写 。3. 执行过程
- fork 子进程:Redis 主进程调用
fork
函数创建一个子进程,子进程负责进行 AOF 重写工作。在这个过程中,主进程和子进程共享内存数据,这样可以避免复制大量数据带来的性能开销。- 子进程重写:子进程遍历当前数据库中的所有键值对,根据键值对的类型和状态生成对应的最小命令集合,并写入到一个临时的 AOF 重写文件中。
- 主进程处理新写命令:在子进程进行 AOF 重写期间,主进程依然可以正常处理客户端的请求。对于新收到的写命令,主进程一方面会将其追加到现有的 AOF 文件中,以保证数据的实时持久化;另一方面会将这些新写命令记录到一个内存缓冲区(AOF 重写缓冲区)中。
- 完成重写并替换:当子进程完成 AOF 重写后,会向主进程发送一个信号。主进程收到信号后,会先将 AOF 重写缓冲区中的所有写命令追加到新的 AOF 重写文件中,以保证新 AOF 文件中的数据和当前数据库状态一致。然后,主进程会原子性地用新的 AOF 重写文件替换掉原来的 AOF 文件,完成 AOF 重写操作。
通过 AOF 重写机制,Redis 可以在保证数据完整性的前提下,有效控制 AOF 文件的大小,提升数据恢复效率和磁盘空间利用率。
优点:
- 数据安全性更高,可以配置不同的同步策略
- AOF 文件是可读的文本文件,包含所有操作命令,便于分析和修改
缺点:
- AOF 文件通常比 RDB 文件大
- 恢复数据的速度比 RDB 慢
- 在高负载下可能会影响性能
4. 混合持久化(Redis 4.0+)
Redis 4.0 引入了混合持久化机制,结合了 RDB 和 AOF 的优点:
- 快照以 RDB 格式写入文件开头
- 之后的增量数据以 AOF 命令格式存储
配置方式:
# 开启混合持久化
aof-use-rdb-preamble yes
5.对于信号的简单解释
6. 如何选择持久化方式
- 如果需要快速恢复且可以接受少量数据丢失,选择 RDB
- 如果需要更高的数据安全性,选择 AOF
- 对于关键业务,推荐使用混合持久化或同时启用 RDB 和 AOF
可以通过 CONFIG SET
命令动态修改持久化配置,也可以使用 SAVE
或 BGSAVE
命令手动触发 RDB 快照,使用 BGREWRITEAOF
命令重写 AOF 文件。