Redis 持久化机制简介【Redis 系列之三】

〇、前言

Redis 持久化主要有两种:RDB(数据快照模式)、AOF(追加模式),另外就是这两种模式的混合模式用。

本文将对这三种情况进行详细介绍。

博主 Redis 相关文章都在这里了:https://www.cnblogs.com/hnzhengfy/category/2229717.html

一、RDB(数据快照模式)

1.1 简介

RDB(Redis Database Snapshot 快照)是 Redis 数据持久化的一种方式,又称为 Snapshot,默认情况下 Redis 在指定的时间间隔内将内存中的数据集快照写入磁盘,存放在副本文件中。当 Redis 重启后又自动读取到内存中。

  • 工作原理

**创建子进程:**在执行 RDB 快照时,Redis 会调用 fork 函数创建一个子进程,尽管Redis本身是单线程运行的。这个子进程与父进程共享内存空间,但拥有独立的地址空间。

**写入数据:**子进程遍历数据库中的每个键值对,并将其序列化后写入到一个新的 RDB 文件中。在这个过程中,主进程仍然可以处理客户端的请求,不会受到磁盘写入操作的影响。

**替换原有文件:**当子进程完成写入操作后,它会用新生成的 RDB 文件替换掉原有的 RDB 文件,从而完成一次完整的快照过程。

关于 fork(),它是 Unix 和类 Unix 操作系统(如 Linux)中的一个关键系统调用,用于创建一个新的进程,这个新进程是原进程的副本,称为子进程。原进程则被称为父进程。fork() 的主要作用是在程序中实现并行处理和任务分解。

  • 为什么需要使用 fork 函数来创建子进程?

避免阻塞主线程: Redis 的主要任务是处理客户端请求。**如果直接在主线程中生成 RDB 文件,那么在生成过程中,主线程将无法处理其他客户端请求,这会导致服务暂时不可用。**通过 fork() 创建一个子进程来执行这个耗时的操作,可以确保主线程继续响应客户端请求。

保证数据一致性:fork() 创建的子进程会继承父进程的数据段(包括内存中的键值对)。这意味着,在子进程开始生成 RDB 文件的那一刻,它所看到的数据是一个完整的、一致的快照。这样即使在生成 RDB 文件的过程中有新的写操作发生,也不会影响到正在生成的 RDB 文件内容。

fork() 生成的子进程拥有与父进程相同的内存映像,但是它是只读的。也就是说,子进程和父进程共享同一块物理内存,直到其中一方尝试修改这块内存的内容(这被称为"写时复制",Copy-On-Write) 。即当父进程或子进程试图修改某一块内存时,操作系统会为该块内存分配一个新的副本,只有在这个时候才会实际复制数据。因此,在生成RDB文件的过程中,除非有大量写操作发生,否则父子进程之间实际上不需要进行大量的内存复制,从而提高了效率

如下示意图:

  • RDB 模式的优势

高性能: 由于使用了 fork() 创建的子进程,主进程不会被磁盘写入操作阻塞,从而保持了 Redis 的高性能。
适合大规模数据恢复: RDB 文件是一个紧凑的二进制文件,包含了当前数据库中所有的键值对数据和对应的过期时间。当需要恢复数据时,Redis 可以直接从 RDB 文件加载数据,而不需要重新执行所有的写操作,从而实现快速恢复。
**空间效率高:**相对于 AOF(Append-Only File)持久化来说,RDB 文件占用更少的磁盘空间,易于传输和存储。

  • RDB 模式的劣势

数据丢失风险: 持久化的数据可能会出现丢失的情况。因为在持久化进行过程中,或者在未到触发备份的节点但已有数据发生变更 ,这时服务器突然宕机,存储的数据可能并不完整。
Fork 耗时问题: 如果数据集很大 ,Fork 可能会很耗时,并且如果 CPU 性能不好的话,可能会导致 Redis 在几毫秒甚至一秒钟内停止为客户端提供服务。
配置项复杂性增加: 需要仔细配置触发快照的条件(例如,在多少秒内有多少键发生变化),以平衡性能和数据安全的需求。错误的配置可能导致过多或过少的快照生成,影响系统性能或数据安全性。

1.2 触发方式一:自动触发

  • 配置触发

在Redis的配置文件中,可以通过设置save m n参数来指定在多长时间内数据集存在多少次修改时自动触发RDB快照。

例如,save 900 1表示在 900 秒内至少有 1 个键被修改时触发 RDB 快照。

其他相关的配置项:

stop-writes-on-bgsave-error:默认情况下,如果 RDB 快照过程中出现错误,Redis 会继续接受写操作。可以通过设置该选项为 yes,让 Redis 在 RDB 快照出错时停止写操作,以避免数据丢失

rdbchecksum:默认开启,表示在存储快照后,Redis 使用 CRC64 算法来进行数据校验。这个操作会增加一定的性能消耗,如果希望获取最大的性能提升,可以关闭此功能。
rdbcompression:用于配置是否对磁盘中的快照文件进行压缩存储。 如果是的话,Redis 会采用 LZF 算法进行压缩,可以减少磁盘空间的占用,但会消耗一定的 CPU 性能。如果不希望消耗 CPU 性能来进行压缩,可以设置为 no 关闭此功能。

dbfilename:用于生成的快照文件的名字 ,默认为 dump.rdb。

dir:配置生成的快照文件存储的位置,默认为当前目录下。

  • 主从复制触发

在主从复制过程中,如果从节点执行全量复制操作,主节点会自动执行 bgsave 命令,来生成 RDB 文件并发送给从节点。

  • 执行特定命令触发

执行 debug reload 命令重新加载 Redis 时,也会自动触发 save 操作。

  • 关闭 Redis 触发

默认情况下,执行 shutdown 命令时,如果没有开启 AOF 持久化功能,则自动执行 bgsave。

1.3 触发方式二:手动触发

  • save 命令

执行该命令会阻塞当前 Redis 服务,直到 RDB 快照生成完成为止。

这种方式在数据量大的时候可能会造成长时间阻塞,因此不建议在生产环境中使用。

示例命令:redis-cli save

  • bgsave 命令

Redis 主进程会 fork 一个子进程来处理 RDB 快照生成任务,而主进程可以继续处理其他命令请求,即**"写时复制"(Copy-On-Write)**。

这种方式对主进程性能影响较小,但 fork 操作本身可能会有一定的性能开销。

示例命令:redis-cli bgsave

执行上述命令后,Redis 会返回"Background saving started"的消息,表示 RDB 快照正在生成中。当快照生成完成后,Redis 会返回"OK"消息,并更新相关的统计信息。

二、AOF(追加模式)

2.1 简介

Redis 的 AOF(Append Only File)持久化策略,通过记录服务器接收到的每个 set、del 等操作命令到日志文件中,当 Redis 重启时,它会重新执行这些命令来恢复数据。

  • 工作原理

命令追加:Redis 服务器在执行写命令时,会将命令以协议格式追加到 AOF 缓冲区中。这些命令包括 SET、DEL 等对数据库进行修改的操作,而读操作不会被记录。

写入文件:AOF 缓冲区中的数据会被周期性地写入磁盘文件中的 AOF 文件。写入的频率可以通过配置文件中的 appendfsync 参数来设置,该参数决定了何时将缓冲区内容同步到磁盘上。

重写机制:随着时间的推移,AOF 文件可能会变得非常大,为了减小文件大小和提高恢复速度,Redis 提供了 AOF 文件重写功能。重写过程会创建一个新的 AOF 文件,将当前内存中的数据以命令序列的方式写入新文件,然后替换原有的 AOF 文件。重写过程中不包含对已过期或已被删除数据的写命令,因此可以显著减少 AOF 文件的大小。

注意:AOF 新文件,也是在 disk 磁盘上的。

  • 配置选项

appendfsync:这个参数用于设置 AOF 持久化的同步策略,它有三个可选值:

  1. **always:每次写操作后同步(数据零丢失,性能最低)。**这种策略确保了最高的数据安全性,但会对性能产生较大影响,因为它需要在每次写操作后都等待磁盘写入完成。
  2. **everysec:每秒同步一次(默认策略)。**这是最常用的策略,它在性能和数据安全性之间取得了较好的平衡。Redis 每秒将 AOF 缓冲区的内容写入磁盘一次,这样即使在发生故障时,最多只会丢失最近一秒的数据。
  3. no:由操作系统决定同步时机。 这种策略效率最高,但对数据安全性的影响也最大。在这种模式下,Redis 不会主动进行磁盘同步操作,而是依赖操作系统的文件缓存机制来决定何时将数据写入磁盘。

auto-aof-rewrite-percentage:用于设置触发 AOF 重写的增长百分比。例如,如果将其设置为 100%,则表示当 AOF 文件的大小比上次重写后增长了 100% 时,就会触发 AOF 重写。

auto-aof-rewrite-min-size:用于设置触发 AOF 重写的最小文件大小。只有当 AOF 文件达到这个指定的大小以上时,才会考虑是否触发重写。

注意:auto-aof-rewrite-percentage 和 auto-aof-rewrite-min-size 这两个配置项需要同时满足才会触发 AOF(Append Only File)重写操作。

  • AOF 模式的优势

数据安全性高: 相较于 RDB,AOF 提供更高的数据安全性,尤其是在频繁更新的场景下。由于AOF是以追加方式记录操作日志,因此即使在崩溃后也能最大限度地恢复数据。即使中途服务器宕机,或者 AOF 文件出现了写入错误或者损坏,也可以通过 redis-check-aof 工具解决数据一致性问题,或者通过 redis-check-rdb 工具来从 AOF 文件中恢复 RDB 文件。
可读性好: AOF文件是一个文本文件,可以通过简单的文本编辑工具查看和修改,更加友好和可读。
**支持秒级同步:**根据配置文件中的 appendfsync 选项,有三种同步策略:always、everysec 和 no,可以按需灵活配置。

通过 redis-check-aof 工具来解决数据一致性问题的简单步骤:

  1. 备份原始AOF文件。避免修复过程中出现问题,破坏原始文件的状态,造成额外的损失。
  2. 检查 AOF 文件的损坏情况。工具会输出检查结果,显示文件中存在的错误类型、错误位置以及可能的修复建议。
  3. 修复 AOF 文件。根据检查结果选择合适的修复方法:如果AOF文件的错误较少且简单,可以尝试手动修复;对于更复杂的错误,可能需要使用专业的文本编辑工具或脚本进行处理。也可以使用 redis-check-aof 工具自动修复。执行带有 --fix 选项的 redis-check-aof 命令,工具会自动尝试修复文件中的错误。但需要注意,自动修复可能会导致一些数据丢失或不一致的情况。
  4. 验证修复后的 AOF 文件。启动 Redis 服务器并加载修复后的文件,确认数据能够正常加载。然后再检查数据完整性,可以通过执行一些查询操作或与备份数据进行比较,来验证修复后的AOF文件中的数据是否与预期一致。如果发现数据仍然存在问题,可能需要重新检查和修复AOF文件。
  • AOF 模式的劣势

文件体积较大:由于 AOF 记录的是每一个写命令,所以其文件大小通常比 RDB 大很多。不过,Redis 支持 AOF 重写(rewrite),可以压缩 AOF 文件大小。

恢复速度较慢:与 RDB 相比,从 AOF 文件恢复数据的速度要慢一些,因为它需要重新执行所有的命令。

性能开销较高:AOF 持久化需要对每个写命令进行同步操作,而 RDB 持久化只需要定期执行快照操作。特别是在"always"同步策略下,AOF 持久化会显著降低 Redis 的吞吐量。

2.2 触发方式一:自动触发

自动触发依赖配置参数,当满足特定条件时,Redis 会自动执行 AOF 重写。

自动触发就是依赖 auto-aof-rewrite-percentage 和 auto-aof-rewrite-min-size 这两个配置项的值。

当两个配置项同时满足时,自动触发。

简单示例:

复制代码
# 当 AOF 日志大小至少为 64mb,并且增长超过了上次重写后的 100% 时,触发 AOF 重写
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

2.3 触发方式二:手动触发

手动触发允许用户通过 Redis 命令主动执行 AOF 文件的重写操作。

使用bgrewriteaof命令手动触发 AOF 重写。

  • 大概工作流程

Fork 子进程:Redis 主进程会通过 fork() 创建一个子进程。

子进程生成新 AOF 文件:子进程基于当前内存数据生成一个新的紧凑 AOF 文件(临时文件)。

主进程处理新写入命令:在子进程生成新 AOF 文件期间,主进程继续处理客户端请求,并将新写入的命令暂存到 AOF 重写缓冲区(aof_rewrite_buf)。

合并数据:子进程完成新 AOF 文件后,主进程将重写缓冲区中的新命令追加到新文件中。

替换旧文件:新 AOF 文件生成后,替换旧的 AOF 文件,完成重写。

复制代码
# 手动触发 AOF 重写
redis-cli BGREWRITEAOF
# 查看重写进度(可选)
redis-cli INFO persistence

三、混合模式(RDB + AOF)

3.1 简介

Redis 4.0 引入:允许在 AOF 重写时,将内存数据以 RDB 快照的形式写入 AOF 文件的开头,后面追加增量的 AOF 命令。

混合模式目的就是,结合 RDB 的快速恢复和 AOF 的数据完整性,使两者优势互补,以达到最佳效果。

  • 工作原理

**AOF 重写触发:**当满足 auto-aof-rewrite-percentage 和 auto-aof-rewrite-min-size 条件时,生成混合 AOF 文件:

  1. RDB 快照部分:子进程将当前内存数据以 RDB 格式写入新文件的开头(aof-preamble)。
  2. AOF 增量部分:将重写期间的新写命令以 AOF 格式追加到文件末尾。

**文件替换:**新文件(如 appendonly.aof_tmp)原子替换旧的 AOF 文件。

  • 数据恢复大致流程

加载 RDB 快照:快速恢复到重写时的内存状态。

重放 AOF 增量:应用新写入的命令,确保数据一致性。

例如,在一个数据库备份恢复的场景中,先加载RDB获取大部分数据,再通过AOF恢复近期的修改,确保数据的完整性。

  • 混合模式的优势

恢复速度快:RDB 快照提供快速恢复基础,AOF 增量补全数据。

数据安全性高:AOF 记录所有写操作,减少数据丢失风险。

文件体积优化:RDB 部分压缩了冗余命令。

  • 混合模式的劣势

文件结构复杂:混合文件需同时支持 RDB 和 AOF 格式解析。

磁盘空间需求:可能比纯 AOF 占用更多空间。

混合模式与两个单独模式的对比:

特性 纯 RDB 纯 AOF 混合模式
恢复速度 快(二进制) 慢(逐行解析) 快(RDB 基础 + AOF 增量)
数据丢失风险 快照间隔内可能丢失数据 根据同步策略(如 1 秒内) 最小化丢失(AOF 保障)
文件体积 中(RDB 压缩 + AOF 增量)
适用场景 数据量小,对恢复速度要求高 数据量大,需高安全性 需平衡速度与数据完整性

3.2 配置方法

总共涉及四个配置项,如下:

复制代码
# 启用 AOF:
appendonly yes
# 开启混合持久化:
aof-use-rdb-preamble yes
# 配置 AOF 重写条件:
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

参考:https://blog.csdn.net/Seky_fei/article/details/106594029**https://tongyi.aliyun.com/qianwen/

相关推荐
江沉晚呤时1 小时前
深入解析 .NET 中的依赖项加载机制:原理、实现与最佳实践
前端·数据库·c#·.netcore
高锰酸钾_1 小时前
Redis如何实现持久化
数据库·redis·缓存
运维自动化&云计算1 小时前
使用Aspera高速上传文件到ncbi
数据库·ncbi上传·aspera
小池先生6 小时前
redis长时间未请求,无法自动重连,报异常org.springframework.data.redis.RedisSystemException
数据库·redis·缓存
zhglhy8 小时前
mysql与redis的日志策略
数据库·redis·mysql
tpoog9 小时前
MySQL:数据库基础
linux·c语言·开发语言·数据库·redis·mysql
傻啦嘿哟10 小时前
python中time模块的常用方法及应用
开发语言·数据库·python
Lightning_201710 小时前
软考中级-数据库-5.3-Internet基础知识
linux·网络·数据库·职场和发展
车载诊断技术11 小时前
电子电气架构 --- 汽车面对软件怎么“破局“?
数据库·人工智能·架构·汽车·电子电器框架·汽车面对软件怎么破局·智能电动汽车概述