【Redis】深入理解 Redis 持久化机制 —— RDB 和 AOF


一、Redis 的持久化

虽然 Redis 是一个内存数据库,但由于各种原因,如 Redis 服务器的重启、意外崩溃等,内存中的数据可能会丢失。为了确保数据的持久性和可靠性,Redis引入了持久化机制,允许将数据定期保存到磁盘中,以便在下次启动 Redis 时能够恢复原来的数据到内存中。

Redis 的持久化机制是 Redis 数据库的一个重要组成部分,它允许将内存中的数据以不同的方式写入磁盘,以防止数据丢失。这对于许多应用场景非常关键,特别是需要长期保存数据或具有高可用性要求的系统。

在本文中,将深入探讨 Redis 的两种主要持久化机制,即 RDB(Redis DataBase)和 AOF(Append-Only File),以及它们的工作原理、优缺点和如何配置它们。此外,还将介绍混合持久化的概念,这是一种结合了 RDB 和 AOF 的方式,以充分利用它们各自的优势。通过本文的阅读,希望可以帮助读者更好地了解 Redis 持久化机制,以便根据实际的应用需求进行正确的配置和管理。

二、RDB 持久化机制

2.1 对 RBD 的认识

RDB 的概念

RDB(Redis DataBase)是 Redis 的一种持久化方式,它用于将当前内存中的数据保存到硬盘上的一个快照(snapshot)文件中。这个快照文件包含了一个特定时刻的所有数据,包括键值对、数据结构等。RDB 的工作方式类似于数据库的备份,它将内存中的数据定期保存到一个持久化文件中,以便在需要时进行数据恢复。

RDB 持久化机制的优缺点

优点:

  1. 高性能: RDB持久化机制在性能上表现出色。因为RDB是通过 fork 子进程来完成的,主进程不需要执行繁重的 IO 操作,这可以确保Redis 在生成 RDB 快照时保持高吞吐量。

  2. 紧凑和可读性好: RDB 文件采用了一种高效的二进制格式,可以很好地保存数据,并且非常紧凑。这使得 RDB 文件既节省磁盘空间,又具有很高的可读性,方便备份和迁移

  3. 适用于灾难恢复: RDB 文件是完整的数据库快照,可以用于从灾难中恢复数据,例如硬盘故障或不可逆的数据损坏。

  4. 备份和迁移: 由于 RDB 文件的紧凑性和可读性,它非常适用于备份数据或在不同环境之间迁移 Redis 数据。

  5. 节省磁盘空间: 可以根据需要配置 RDB 的保存频率,从而在一定程度上控制磁盘空间的占用。

缺点:

  1. 数据可能有损失: RDB 是定期生成的快照文件,如果 Redis 服务器在生成快照之间崩溃,可能会丢失最后一次快照之后的数据。

  2. 不适用于大规模数据: 在处理大规模数据时,生成 RDB 文件可能会导致较长时间的阻塞,影响性能。在某些情况下,阻塞时间可能会变得不可接受。

  3. 不适用于实时持久化需求: RDB 是基于快照的,因此不能提供实时持久化。如果需要每个写操作都立即持久化到磁盘,RDB 可能不是最佳选择。

  4. 配置文件的修改: 如果频繁地修改Redis的配置文件,RDB可能就变得不适合,因为它只有在 Redis 服务器正常关闭时才会生成快照。这可能会导致在配置更改后发生数据丢失。

总之,RDB 持久化机制在性能、备份和紧凑性方面表现出色,适用于许多使用场景,但需要注意数据可能会有损失,并且在处理大规模数据时需要慎重考虑。如果对实时持久化有更高要求,可以考虑使用 AOF 持久化机制或混合持久化来弥补 RDB 的不足。

RDB 的相关配置

Redis的RDB持久化可以通过在Redis配置文件(通常是redis.conf)中进行相关配置。以下是一些与RDB持久化有关的常见配置项:

  1. 保存快照的频率:

    save 900 1        # 表示在900秒(15分钟)内,如果至少有1个键发生变化,就会触发RDB快照保存。
    save 300 10       # 表示在300秒(5分钟)内,如果至少有10个键发生变化,就会触发RDB快照保存。
    save 60 10000     # 表示在60秒内,如果至少有10000个键发生变化,就会触发RDB快照保存。
    

    这些配置项定义了 RDB 持久化的触发条件。根据具体的应用需求,就可以根据不同的时间间隔和键变化数来触发 RDB 快照。

  2. RDB文件名和路径:

    dbfilename dump.rdb    # 指定RDB快照文件的名称
    dir /var/lib/redis     # 指定RDB文件的保存路径
    

    这些配置项允许指定 RDB 快照文件的名称和保存路径。注意需要确保文件夹存在并具有适当的权限。

  3. 禁用 RDB 自动持久化:

    save ""              # 禁用自动RDB持久化
    

    如果想禁用自动触发的 RDB 持久化,可以将save配置项设置为空字符串。

  4. RDB 持久化压缩:

    rdbcompression yes  # 开启 RDB 文件压缩(默认情况下是开启的)
    

    这个配置项控制是否对生成的RDB文件进行压缩,开启后可以减小 RDB 文件的大小,但会占用额外的 CPU 资源。

  5. 检查点文件:

    rdbchecksum yes     # 在保存RDB文件时是否进行校验和检查(默认情况下是开启的)
    

    这个配置项控制是否在保存 RDB 文件时进行校验和检查,以确保文件的完整性。

请注意,要使配置更改生效,就需要重启 Redis 服务器。根据具有的应用需求和数据量,可以调整这些配置项,以满足性能和持久性的要求。

2.2 RDB 的触发时机

2.2 RDB 的触发时机

RDB的触发时机分为自动触发和手动触发两种方式:

自动触发

自动触发是通过配置文件中的保存快照的频率来实现的。在 Redis 的配置文件(redis.conf)中,可以设置一个或多个save指令来定义何时自动触发 RDB 快照的保存。每个save指令都有两个参数,第一个参数是时间间隔(单位为秒),第二个参数是发生变化的键的数量。

例如,以下是一个保存快照的自动触发配置示例:

save 900 1        # 表示在900秒(15分钟)内,如果至少有1个键发生变化,就会触发RDB快照保存。
save 300 10       # 表示在300秒(5分钟)内,如果至少有10个键发生变化,就会触发RDB快照保存。
save 60 10000     # 表示在60秒内,如果至少有10000个键发生变化,就会触发RDB快照保存。

这些配置项定义了 RDB 自动触发快照保存的条件。Redis 会定期检查这些条件,如果满足其中任何一个条件,就会触发RDB快照的生成。

当然如果配置了save "",则会禁止自动触发。

手动触发:SAVE 和 BGSAVE

手动触发 RDB 快照是通过 Redis 的命令来实现的,主要有两个命令可用:

  1. SAVE命令: 使用 SAVE 命令可以立即生成一个 RDB 快照,它会阻塞 Redis 服务器,直到 RDB 快照生成完成为止。这个命令不常用,因为它会导致 Redis 服务器在生成快照期间停止响应其他请求

语法:

SAVE
  1. BGSAVE命令: 使用 BGSAVE 命令可以在后台生成 RDB 快照,而不会阻塞 Redis 服务器的正常操作,这是通常推荐的手动触发方式。
BGSAVE

BGSAVE 命令会使用操作系统提供的 fork 系统调用启动一个子进程,该子进程负责生成 RDB 快照文件,而主进程继续响应其他请求。一旦生成完成,BGSAVE 会将 RDB 文件保存到磁盘,然后通知主进程。

BGSAVE 命令的运作流程:

说明:

  1. 执行 BGSAVE 命令时,Redis 父进程首先会判断当前进是否存在其他正在执行的子进程,例如执行 RDB或者AOF 相关命令的子进程,如果存在,此时的 BGSAVE 命令则会直接返回。
  2. 父进程会执行 fork 创建子进程,fork 的过程中父进程会阻塞,通过 info stats 命令查看 latest_fork_usec 选项,可以获取最近一次 fork操作的耗时,单位为微秒。
  3. 父进程执行 fork 完成后,BGSAVE 命令会返回 “Background saving started” 信息,此后将不再阻塞父进程,可以继续响应其他命令。同时子进程负责生成 RDB 快照文件。
  4. 子进程在创建 RDB 文件时,会根据父进程的内存生成临时的快照文件,完成后会对原有dump.rdb文件进行原子替换。执行 lastsave命令可以获取最后⼀次生成 RDB 的时间,对应 info 统计的 rdb_last_save_time 选项。
  5. 子进程创建RDB文件完成后会发送信号给父进程表示完成了,父进程则会更新统计信息。

手动触发RDB快照通常用于备份 Redis 数据、手动管理持久化策略或在执行某些操作前创建数据的一致性快照。总之,RDB 的触发时机可以通过自动触发和手动触发两种方式来实现,具体取决于具体的应用需求和管理策略。自动触发是定期保存的机制,而手动触发则允许您在需要时立即创建RDB快照。

2.3 RDB 文件的处理

RDB文件是 Redis 数据库的快照文件,它保存了当前内存中的数据以便在需要时进行恢复。以下是关于RDB文件的处理和管理的重要信息:

保存 RDB 文件

  1. 文件保存路径: RDB 文件保存在 Redis 配置文件中指定的目录下,默认情况下是/var/lib/redis/。文件名由配置文件中的dbfilename参数指定,默认为 “dump.rdb”。可以在 Redis 运行时使用 CONFIG SET 命令动态更改保存目录和文件名,例如:

    CONFIG SET dir /new/directory/
    CONFIG SET dbfilename newdump.rdb
    

    这将使RDB文件保存到新的目录和使用新的文件名。

  2. 手动保存: 可以通过执行SAVEBGSAVE命令来手动触发 RDB 文件的保存。SAVE命令会在 Redis 服务器生成 RDB 文件的同时阻塞其他请求,而 BGSAVE 命令会在后台生成 RDB 文件,不会阻塞其他操作。

      SAVE
    BGSAVE
    

压缩 RDB 文件

Redis默认采用 LZF 算法对生成的 RDB 文件进行压缩处理,以减小文件的体积,节省磁盘空间和网络带宽。压缩是默认开启的,但我们可以通过以下命令动态修改:

CONFIG SET rdbcompression yes   # 开启RDB文件压缩
CONFIG SET rdbcompression no    # 禁用RDB文件压缩

虽然压缩RDB文件会消耗CPU资源,但通常建议开启,特别是在磁盘空间和网络带宽有限的情况下,因为它可以显著减小文件的大小。

校验 RDB 文件

Redis 在启动时会加载 RDB 文件,如果文件损坏或格式错误,Redis 将拒绝启动。为了检查 RDB 文件的完整性和有效性,可以使用Redis提供的 redis-check-rdb 工具。这个工具会检测 RDB 文件并生成相应的错误报告,帮助我们识别和解决问题。

检查 RDB 文件:

处理和管理RDB文件是确保Redis数据持久性和可靠性的重要任务。了解如何保存、压缩和校验RDB文件可以帮助我们更好地管理 Redis 数据库。

三、AOF 持久化机制

3.1 对 AOF 的认识

AOF 的概念

AOF(Append-Only File)是 Redis 的一种持久化机制,用于将 Redis 服务器的写操作以追加的方式记录到一个文本文件中,从而实现数据持久化。每个写操作都会以 Redis 命令的形式追加到 AOF 文件的末尾,因此 AOF 文件是一个按照时间顺序记录写操作的日志文件。

AOF 的优缺点

优点:

  1. 数据安全性:AOF 记录了每个写操作,因此在服务器故障或崩溃时,只会丢失最后一次写操作之后的数据。这提供了较高的数据安全性。

  2. 可读性:AOF 文件是一个文本文件,易于人类阅读和理解。这使得AOF文件在需要手动恢复数据或进行调试时非常有用。

  3. 灵活性:AOF 文件的追加方式写入使得数据持久化非常实时,可以根据需求选择不同的同步策略,从完全同步到异步。

  4. 自动重写:Redis 提供了 AOF 文件的自动重写机制,可以避免 AOF 文件过大,提高了性能。

缺点:

  1. 文件体积:相对于 RDB 持久化,AOF 文件通常较大,因为它包含了每个写操作的命令文本。这可能会占用较多的磁盘空间。

  2. 写入性能:AOF 持久化会导致每个写操作都需要追加到 AOF 文件中,这可能会对写入性能产生一定的影响,尤其是在使用同步写入策略时。

AOF 的相关配置

在Redis中,可以通过配置文件或使用 CONFIG 命令来配置 AOF 持久化的相关参数。以下是一些常用的 AOF 配置选项:

  • appendonly:用于启用或禁用AOF持久化。设置为"yes"表示启用AOF,设置为"no"表示禁用。默认情况下,AOF持久化是禁用的,需要手动启用。

  • appendfilename:指定AOF文件的文件名,默认为"appendonly.aof"。您可以根据需要更改文件名。

  • appendfsync:指定AOF文件同步到磁盘的策略。可以选择的选项包括"always"(每次写操作都同步)、“everysec”(每秒同步一次)和"no"(完全异步)。

  • auto-aof-rewrite-percentageauto-aof-rewrite-min-size:用于配置 AOF 自动重写的触发条件。前者表示 AOF 文件的大小相对于上一次重写时的大小增长了多少百分比时触发重写,后者表示 AOF 文件的最小大小。

这些配置选项可以在Redis的配置文件(通常是redis.conf)中找到,也可以通过CONFIG命令进行动态设置。根据您的需求和应用场景,可以灵活配置 AOF 持久化以实现数据的持久性和性能要求。

3.2 AOF 的使用

使用演示

当配置完 AOF 相关选项之后,需要使用命令service redis-server restart重启 Redis 服务器,当重启之后,就会发现在和 dump.rdb 文件相同的目录下多了一个 appendonly.aof 文件:


向 Redis 中设置两条数据:

查看 appendonly.aof 文件:

其文件内容就是刚才的写入数据的命令。

突然终止 Redis 服务器,然后再启动:

连接并查询 Redis 数据库,发现数据并没有丢失:

AOF 工作流程

工作流程图示如下:

  1. 所有的写入命令会追加到 aof_buf 缓冲区中。
  2. AOF 缓冲区根据对应的策略向硬盘做同步操作。
  3. 随着 AOF 文 件越来越大,需要定期对 AOF 文件进行重写,达到压缩的目的。
  4. 当 Redis 服务器启动时,会加载 AOF 文件中的命令进行数据恢复。

命令写入:
AOF 命令写入的内容是直接遵循 Redis 的文本协议格式。例如,set hello world 命令在 AOF 缓冲区中以文本协议格式表示如下:

*3\r\n$3\r\nset\r\n$5\r\nhello\r\n$5\r\nworld\r\n

Redis 选择文本协议的原因包括兼容性好、实现简单以及具备可读性等特点。

为什么使用aof_buf 缓冲区:

AOF 缓冲区(aof_buf)的存在是为了提高写入性能。因为 Redis 是单线程响应命令的,如果每次写入都直接同步到硬盘,性能将受到严重影响。通过首先将命令写入缓冲区,Redis 可以有效减少 IO 操作的次数,提高性能。此外,Redis 还提供多种缓冲区同步策略,使用户可以根据性能和数据安全性的需求进行权衡选择。

3.3 AOF 同步文件策略

Redis 提供了多种 AOF 缓冲区同步文件策略,由配置文件(redis.conf)中的参数appendfsync 控制,可配置的值及其说明如下表所示:

可配置值 说明
always 每次通过write 写入 aof_buf 中都会立即强制调用 fsync 将数据同步到磁盘,确保数据安全,但写入性能较差。
everysec 通过 write 操作首先追加到 aof_buf 中,然后每秒执行一次同步操作,将数据同步到 AOF 文件中,以平衡性能和数据安全性。
no 只将写入操作通过 write 追加到aof_buf中,同步操作由操作系统控制。这种配置提供最高的写入性能,但数据安全性较低。

有关系统调用 writefsync 的说明:

  • write 操作触发了延迟写(delayed write)机制。Linux 内核提供页面缓冲区以提高硬盘 I/O 性能。write 操作将数据写入系统缓冲区后立即返回。同步到硬盘的操作依赖于操作系统的调度机制,例如,缓冲区页面满或达到特定时间间隔。如果系统在同步文件之前崩溃或宕机,缓冲区内的数据可能会丢失。

  • fsync是针对单个文件的操作,它执行强制硬盘同步,fsync 会阻塞直到数据被写入到硬盘。

不同的配置值:

  • 配置为always时,每次写入都会强制同步 AOF 文件,这会导致性能很差。在一般的 SATA 硬盘上,只能支持几百个 TPS 的写入。通常不建议配置为always,除非数据非常重要。

  • 配置为no时,由于操作系统同步策略不受控制,虽然提高了性能,但数据丢失的风险大大增加。一般情况下不建议配置为no,除非数据的重要性很低。

  • 配置为everysec是默认配置,也是推荐的配置选项,它兼顾了数据安全性和性能。理论上最多只会丢失1秒的数据。

这些配置选项允许用户根据性能和数据安全性的需求来选择适合的 AOF 同步策略。

3.4 AOF 重写机制

为什么要进行 AOF 文件的重写

进行 AOF 文件的重写是为了解决 Redis 中可能存在的大量无效命令积累的问题。让我们通过一些简单的例子来说明:

在 Redis 中,执行了以下一系列写入命令:

SET key1 123
SET key1 hello
SET key1 world
SET key1 123

尽管上面执行了 4 条写入命令,但最终在 Redis 中只存在最后一条命令写入的数据,也就是key1的值为123

同样,执行了以下一系列写入命令:

SET key2 123
SET key2 hello
SET key2 world
SET key2 123
DEL key2

虽然上面执行了 5 条写入命令,但最终 key2 在 Redis 中并不存在。

  • 例如在 Redis 中执行下列命令:

  • 重写前:

  • 重写后:

此时发现出现了乱码,即是以二进制的形式储存的,发生这样的原因是因为同时开启了AOP 和 RDB ,因此此时 Redis 采取的持久化策略就是混合持久化了。

  • 使用 Redis 提供的检查工具redis-check-aof 检查 AOF 文件,可以发现 AOF 文件是合法的:

通过上面两个简单的例子可以得出:

  • 如果没有 AOF 文件的重写机制,Redis 将持续存储大量无效的命令,这会导致 AOF 文件变得庞大,占用大量磁盘空间,并且降低 AOF 文件的读取性能。
  • AOF 文件的重写通过将这些无效命令清除,生成一个更加紧凑和高效的新 AOF 文件,解决了这个问题。新的 AOF 文件只包含有效的写入命令,这有助于减小文件体积,提高读取性能,并确保不丢失任何有效数据。这是为什么要进行AOF文件的重写的原因。

AOF 重写的触发方式

AOF文件的重写可以通过以下两种方式触发:

  1. 手动触发:通过调用 Redis 提供的BGREWRITEAOF命令,可以手动触发 AOF 文件的重写过程。这个命令会立即开始 AOF 文件的重写,而不会影响 Redis 的正常运行。

  2. 自动触发:Redis 也支持自动触发 AOF 文件的重写,触发的时机是基于两个配置参数来决定的:

    • auto-aof-rewrite-min-size:这个参数定义了AOF文件的最小大小,以MB为单位。默认值为64MB。只有当AOF文件的大小超过这个阈值时,才会考虑触发自动重写。

    • auto-aof-rewrite-percentage:这个参数定义了AOF文件大小相对于上次重写后的增长比例,以百分比表示。默认值为100%。如果AOF文件的大小增长超过了上次重写后的这个百分比,就会触发自动重写。

    例如,如果将auto-aof-rewrite-min-size设置为64MB,auto-aof-rewrite-percentage设置为100%,那么只有当AOF文件的大小超过64MB,并且比上次重写后增长了100%或更多时,自动重写才会被触发。

自动触发AOF文件的重写是为了确保AOF文件不会无限制地增长,同时避免过于频繁地执行重写操作。这样可以在不丢失任何数据的情况下,保持AOF文件的合理大小,提高性能,并减少磁盘空间的占用。

AOP 重写的执行流程


AOP 重写的执行流程如下:

  1. 执行 AOF 重写请求。

    • 如果当前进程正在执行 AOF 重写,请求不执行。
    • 如果当前进程正在执行 bgsave 操作,重写命令将延迟到 bgsave 完成后再执行。
  2. 父进程执行 fork 创建子进程。

  3. 重写过程:
    a. 主进程在 fork 之后继续响应其他命令。所有修改操作会被写入 AOF 缓冲区,并根据 appendfsync 策略同步到硬盘,以确保旧 AOF 文件机制的正确性。
    b. 子进程只有 fork 之前的所有内存信息,所以父进程需要将 fork 之后这段时间内的修改操作写入 AOF 重写缓冲区中。

  4. 子进程根据内存快照,将命令合并到新的 AOF 文件中。

  5. 子进程完成重写:
    a. 新文件写入后,子进程发送信号给父进程。
    b. 父进程将 AOF 重写缓冲区内临时保存的命令追加到新 AOF 文件中。
    c. 使用新 AOF 文件替换旧 AOF 文件。

四、混合持久化

混合持久化是指 Redis 同时使用 AOF(Append-Only File)和 RDB(Redis Database)两种持久化方式来保障数据的持久性。这种策略结合了两种不同的持久化方法,以兼顾不同的需求和场景。

下面是混合持久化的工作原理和优点:

1. AOF 持久化:

  • AOF 是一种追加写日志文件,记录了每个写操作的命令,以及这些命令的参数。
  • AOF 持久化是实时的,即每个写操作都会追加到 AOF 文件中,确保了数据的完整性。
  • AOF 文件可以用于数据的恢复,Redis可以通过重新执行 AOF 文件中的命令来重建数据状态。

2. RDB 持久化:

  • RDB 是一种快照持久化,它将 Redis 内存中的数据以二进制形式保存到磁盘上。
  • RDB 持久化是点对点的,即在指定的时间间隔内生成一次快照文件,通常是在内存数据发生变化后生成。
  • RDB 文件是一个经过压缩的二进制文件,用于在需要时快速恢复整个数据库的状态。

混合持久化的工作方式:

  • Redis 同时启用了 AOF 和 RDB 持久化方式。
  • AOF 文件会记录每个写操作,而 RDB 文件则会在特定的时间间隔内生成一次快照。
  • 在数据恢复时,Redis 会首先尝试使用 AOF 文件进行恢复,因为它包含了更多的历史命令,可以提供更完整的数据恢复。
  • 如果 AOF 文件损坏或者过大,Redis 可以使用 RDB 文件进行快速的启动,然后再根据 AOF 文件进行数据修复。

混合持久化的优点:

  • 数据安全性:AOF 提供实时的数据追加和历史记录,使得数据更加安全。RDB 提供了快速的恢复方式。
  • 性能:AOF 的写操作相对 RDB 更加高效,而 RDB 提供了快速的数据恢复。
  • 灵活性:混合持久化允许根据不同的需求和场景来选择适当的恢复方式。
  • 降低数据损失:由于 AOF 文件包含了历史操作,可以减少数据损失的可能性。

总之,混合持久化将 AOF 和 RDB 两种持久化方式结合起来,兼顾了实时性和恢复性,提供了更全面的数据保护策略,使 Redis 在不同应用场景中更加强大和可靠。但需要注意的是,混合持久化可能会增加存储开销和磁盘 I/O 负载,因此在配置时需要谨慎考虑。

猜你喜欢

转载自blog.csdn.net/qq_61635026/article/details/132892150