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/

相关推荐
小陈工2 小时前
Python Web开发入门(十七):Vue.js与Python后端集成——让前后端真正“握手言和“
开发语言·前端·javascript·数据库·vue.js·人工智能·python
科技小花6 小时前
数据治理平台架构演进观察:AI原生设计如何重构企业数据管理范式
数据库·重构·架构·数据治理·ai-native·ai原生
一江寒逸6 小时前
零基础从入门到精通MySQL(中篇):进阶篇——吃透多表查询、事务核心与高级特性,搞定复杂业务SQL
数据库·sql·mysql
D4c-lovetrain6 小时前
linux个人心得22 (mysql)
数据库·mysql
阿里小阿希7 小时前
CentOS7 PostgreSQL 9.2 升级到 15 完整教程
数据库·postgresql
荒川之神7 小时前
Oracle 数据仓库雪花模型设计(完整实战方案)
数据库·数据仓库·oracle
做个文艺程序员7 小时前
MySQL安全加固十大硬核操作
数据库·mysql·安全
不吃香菜学java7 小时前
Redis简单应用
数据库·spring boot·tomcat·maven
一个天蝎座 白勺 程序猿7 小时前
Apache IoTDB(15):IoTDB查询写回(INTO子句)深度解析——从语法到实战的ETL全链路指南
数据库·apache·etl·iotdb
不知名的老吴8 小时前
Redis的延迟瓶颈:TCP栈开销无法避免
数据库·redis·缓存