Redis 持久性

Redis 如何将数据写入磁盘

Redis 堆栈 Redis 社区版

持久性是指将数据写入持久存储,例如固态磁盘 (SSD)。Redis 提供了一系列持久性选项。这些包括:

  • RDB(Redis 数据库):RDB 持久性按指定的时间间隔执行数据集的时间点快照。
  • AOF(仅附加文件):AOF 持久性记录服务器收到的每个写入作。然后,可以在服务器启动时再次重放这些作,从而重建原始数据集。命令的记录格式与 Redis 协议本身相同。
  • 无持久性:您可以完全禁用持久性。这有时在缓存时使用。
  • RDB + AOF:您还可以将 AOF 和 RDB 合并到同一个实例中。

如果您不想考虑这些不同持久性策略之间的权衡,则可能需要考虑 Redis Enterprise 的持久性选项,这些选项可以使用 UI 进行预配置。

要了解有关如何评估 Redis 持久性策略的更多信息,请继续阅读。

RDB 优势

  • RDB 是 Redis 数据的非常紧凑的单文件时间点表示形式。RDB 文件非常适合备份。例如,您可能希望在最近 24 小时内每小时存档一次 RDB 文件,并在 30 天内每天保存一次 RDB 快照。这使您可以在发生灾难时轻松恢复不同版本的数据集。
  • RDB 非常适合灾难恢复,它是一个紧凑的文件,可以传输到远数据中心或 Amazon S3(可能已加密)。
  • RDB 最大限度地提高了 Redis 性能,因为 Redis 父进程为了持久化而需要做的唯一工作是分叉一个子进程,该子进程将完成其余所有工作。父进程永远不会执行磁盘 I/O 或类似作。
  • 与 AOF 相比,RDB 允许更快地重新启动大型数据集。
  • 在副本上,RDB 支持在重新启动和故障转移后进行部分重新同步

RDB 缺点

  • 如果您需要在 Redis 停止工作(例如停电后)的情况下(例如,在停电后)最大限度地减少数据丢失的可能性,则 RDB 不是好的。您可以配置生成 RDB 的不同保存点(例如,在至少 5 分钟并对数据集进行 100 次写入后,您可以拥有多个保存点)。但是,您通常每 5 分钟或更长时间创建一个 RDB 快照,因此,如果 Redis 因任何原因在没有正确关闭的情况下停止工作,您应该准备好丢失最近几分钟的数据。
  • RDB 需要经常 fork() 才能使用子进程在磁盘上持久化。如果数据集很大,fork() 可能会很耗时,如果数据集非常大且 CPU 性能不是很好,可能会导致 Redis 停止为客户端提供服务几毫秒甚至一秒钟。AOF 也需要 fork() 但频率较低,您可以调整重写日志的频率,而无需牺牲持久性。

AOF 优势

  • 使用 AOF Redis 的持久性要高得多:您可以使用不同的 fsync 策略:完全不同步、每秒同步、每次查询时同步。使用每秒 fsync 的默认策略,写入性能仍然很好。fsync 是使用后台线程执行的,主线程将在没有 fsync 正在进行时努力执行写入,因此您只会损失一秒钟的写入时间。
  • AOF 日志是仅追加日志,因此如果停电,则不会搜索,也不会出现损坏问题。即使由于某种原因(磁盘已满或其他原因)日志以写一半的命令结束,redis-check-aof 工具也能轻松修复。
  • Redis 能够在 AOF 变得太大时在后台自动重写 AOF。重写是完全安全的,因为当 Redis 继续附加到旧文件时,会生成一个全新的文件,其中包含创建当前数据集所需的最少作集,一旦第二个文件准备就绪,Redis 就会切换这两个文件并开始附加到新文件。
  • AOF 以易于理解和解析的格式依次包含所有作的日志。您甚至可以轻松导出 AOF 文件。例如,即使您不小心使用FLUSHALL命令,只要在此期间没有对日志执行重写,您仍然可以通过停止服务器、删除最新命令并再次重新启动 Redis 来保存数据集。

AOF 缺点

  • AOF 文件通常比同一数据集的等效 RDB 文件大。
  • AOF 可能比 RDB 慢,具体取决于确切的 fsync 策略。通常,将 fsync 设置为每秒一次时,性能仍然非常高,并且禁用 fsync 后,即使在高负载下,它也应该与 RDB 一样快。尽管如此,即使在写入负载巨大的情况下,RDB 也能够为最大延迟提供更多保证。

Redis < 7.0

  • 如果在重写期间对数据库有写入(这些写入在内存中缓冲并在最后写入新的 AOF),则 AOF 可以使用大量内存。
  • 在重写期间到达的所有写入命令都会被写入磁盘两次。
  • Redis 可以在重写结束时冻结将这些写入命令和 fsync 到新 AOF 文件的写入。

好的,那么我应该使用什么呢?

您应该同时使用这两种持久性方法的一般指示是 if 您希望获得与 PostgreSQL 所能提供的数据安全性相当的程度。

如果您非常关心您的数据,但仍然可以忍受几分钟的 数据丢失 如果发生灾难,您可以简单地单独使用 RDB。

有许多用户单独使用 AOF,但我们不鼓励这样做,因为 RDB 快照是进行数据库备份的好主意, 以更快地重新启动,并在 AOF 引擎中出现错误时。

以下部分将说明有关这两种持久性模型的更多详细信息。

快照

默认情况下,Redis 将数据集的快照保存在磁盘上的二进制文件中 名为dump.rdb.您可以配置 Redis 以使其保存 dataset 每 N 秒一次(如果数据集中至少有 M 个变化), 或者您可以手动调用SAVEBGSAVE命令。

例如,此配置将使 Redis 自动转储 数据集到磁盘(如果至少有 1000 个键发生更改):

save 60 1000

此策略称为快照

运作方式

每当 Redis 需要将数据集转储到磁盘时,都会发生以下情况:

  • Redis 分叉。我们现在有一个孩子 和父进程。

  • 子项开始将数据集写入临时 RDB 文件。

  • 当子项完成对新 RDB 文件的写入后,它会替换旧的 一。

此方法允许 Redis 从写入时复制语义中受益。

仅追加文件

快照不是很持久。如果运行 Redis 的计算机停止,则 您的电源线出现故障,或者您不小心kill -9您的实例、 写入 Redis 的最新数据将丢失。虽然这可能不是什么大事 deal 对于某些应用程序,有一些用例可以实现完全持久性,并且 在这些情况下,单独的 Redis 快照不是一个可行的选择。

仅追加文件是 雷迪斯。它在 1.1 版中可用。

您可以在配置文件中打开 AOF:

appendonly yes

从现在开始,每次 Redis 收到将 数据集(例如SET),它会将其附加到 AOF。重新启动时 Redis 时,它将重放 AOF 以重建状态。

从 Redis 7.0.0 开始,Redis 使用多部分 AOF 机制。 也就是说,原始的单个 AOF 文件被拆分为基本文件(最多一个)和增量文件(可能有多个)。 基本文件表示重写 AOF 时存在的数据的初始(RDB 或 AOF 格式)快照。 增量文件包含自上次创建基本 AOF 文件以来的增量更改。所有这些文件都放在一个单独的目录中,并由一个清单文件进行跟踪。

日志重写

随着写入作的增加,AOF 变得越来越大 执行。例如,如果要将计数器递增 100 次, 您最终会在数据集中得到一个 key,其中包含最终的 值,但 AOF 中有 100 个条目。其中 99 个条目是不需要的 以重建当前状态。

重写是完全安全的。 当 Redis 继续追加到旧文件时, 使用创建当前数据集所需的最少作集生成一个全新的 ID, 一旦第二个文件准备好,Redis 就会切换这两个文件并开始附加到新文件。

所以 Redis 支持一个有趣的功能:它能够重建 AOF 在后台运行,而不会中断对客户端的服务。每当 您发出一个BGREWRITEAOF,Redis 将写入最短的 在内存中重建当前数据集所需的命令。如果你是 将 AOF 与 Redis 2.2 结合使用,您需要运行BGREWRITEAOF不时到 时间。由于 Redis 2.4 能够自动触发日志重写(请参阅 example configuration file 了解更多信息)。

从 Redis 7.0.0 开始,当计划 AOF 重写时,Redis 父进程会打开一个新的增量 AOF 文件以继续写入。 子进程执行重写逻辑并生成新的基本 AOF。 Redis 将使用临时清单文件来跟踪新生成的基本文件和增量文件。 准备就绪后,Redis 将执行原子替换作以使此临时清单文件生效。 为了避免 AOF 重写反复失败和重试时创建大量增量文件的问题, Redis 引入了 AOF 重写限制机制,以确保失败的 AOF 重写以越来越慢的速率重试。

仅追加文件的持久性如何?

您可以配置 Redis 将fsync磁盘上的数据。有 三个选项:

  • appendfsync always:fsync每次将新命令附加到 AOF 时。非常非常慢,非常安全。请注意,在执行来自多个客户端或管道的一批命令后,这些命令会附加到 AOF,因此这意味着一次写入和一次 fsync(在发送回复之前)。
  • appendfsync everysec:fsync每一秒。足够快(从 2.4 版本开始,可能与快照一样快),如果发生灾难,您可能会丢失 1 秒的数据。
  • appendfsync no:从不fsync,只需将您的数据交到作系统手中即可。更快但不太安全的方法。通常,Linux 会使用此配置每 30 秒刷新一次数据,但这取决于内核的确切调整。

建议的(也是默认的)策略是fsync每一秒。是的 既快速又相对安全。这always策略在 中非常慢 实践,但它支持 group 提交,所以如果有多个并行 写入 Redis 将尝试执行单个fsync操作。

如果我的 AOF 被截断,我该怎么办?

可能是服务器在写入 AOF 文件时崩溃,或者 在编写本文时,存储 AOF 文件的卷已满。发生这种情况时, AOF 仍包含表示给定时间点版本的一致数据 数据集中(使用默认的 AOF fsync 时,可能会超过 1 秒 policy),但 AOF 中的最后一个命令可能会被截断。 无论如何,Redis 的最新主要版本将能够加载 AOF,只是 丢弃文件中最后一个格式不正确的命令。在这种情况下, server 将发出如下日志:

* Reading RDB preamble from AOF file...
* Reading the remaining AOF tail...
# !!! Warning: short read while loading the AOF file !!!
# !!! Truncating the AOF at offset 439 !!!
# AOF loaded anyway because aof-load-truncated is enabled

您可以更改默认配置以强制 Redis 在此类 cases,但默认配置是继续,而不管 事实上,文件中的最后一个命令格式不正确,为了保证 重启后的可用性。

旧版本的 Redis 可能无法恢复,并且可能需要以下步骤:

  • 创建 AOF 文件的备份副本。

  • 使用redis-check-aofRedis 附带的工具:

    $ redis-check-aof --fix <filename>
    
  • 可选使用diff -u检查两个文件之间有什么区别。

  • 使用修复的文件重新启动服务器。

如果我的 AOF 损坏了怎么办?

如果 AOF 文件不仅被截断,而且被无效字节损坏 序列在中间,事情就复杂多了。Redis 会抱怨 在启动时,将中止:

* Reading the remaining AOF tail...
# Bad file format reading the append only file: make a backup of your AOF file, then use ./redis-check-aof --fix <filename>

最好的办法是运行redis-check-aof实用程序,最初没有 这--fix选项,然后了解问题,跳转到给定的 offset 的 offset,并查看是否可以手动修复该文件: AOF 使用与 Redis 协议相同的格式,并且很容易修复 手动地。否则,可以让实用程序为我们修复文件,但是 在这种情况下,从无效部分到 文件可能会被丢弃,从而导致大量数据丢失。 损坏恰好位于文件的初始部分。

运作方式

日志重写使用已用于 快照。这是它的工作原理:

Redis >= 7.0

  • Redis 分叉,所以现在我们有一个子 和父进程。

  • 子级开始在临时文件中写入新的基本 AOF。

  • 父级打开一个新的增量 AOF 文件以继续写入更新。 如果重写失败,则旧的 base 和 increment 文件(如果有)以及这个新打开的 increment 文件表示完整的更新数据集。 所以我们是安全的。

  • 当 child 完成对 base 文件的重写时,parent 会收到一个信号 并使用新打开的增量文件和子生成的基本文件来构建临时清单, 并保留它。

  • 利润!现在,Redis 对清单文件进行原子交换,以便此 AOF 重写的结果生效。Redis 还会清理旧的基本文件和任何未使用的增量文件。

Redis < 7.0

  • Redis 分叉,所以现在我们有一个子 和父进程。

  • 子级开始在临时文件中写入新的 AOF。

  • 父级将所有新更改累积在内存中缓冲区中(但 同时,它将新的更改写入旧的仅追加文件 所以如果重写失败,我们是安全的)。

  • 当 child 完成文件重写后,parent 会收到一个信号 并将内存缓冲区附加到由 孩子。

  • 现在 Redis 原子地将新文件重命名为旧文件 并开始将新数据追加到新文件中。

如果我当前正在使用 dump.rdb 快照,如何切换到 AOF?

如果要在当前正在使用 RDB 快照的服务器中启用 AOF,则需要先在实时服务器上通过 CONFIG 命令启用 AOF 来转换数据。

重要提示:不遵循此过程(例如,仅更改配置并重新启动服务器)可能会导致数据丢失!

Redis >= 2.2

准备:

  • 备份最新的 dump.rdb 文件。
  • 将此备份传输到安全的地方。

切换到实时数据库上的 AOF:

  • 启用 AOF:redis-cli config set appendonly yes
  • (可选)禁用 RDB:redis-cli config set save ""
  • 确保将写入正确附加到 append only 文件。
  • 重要:更新您的redis.conf(可能通过CONFIG REWRITE),并确保它与上述配置匹配。 如果您忘记了此步骤,当您重新启动服务器时,配置更改将丢失,服务器将使用旧配置重新启动,从而导致数据丢失。

下次重新启动服务器时:

  • 在重新启动服务器之前,请等待 AOF 重写完成持久化数据。 您可以通过观看来做到这一点INFO persistence,等待aof_rewrite_in_progressaof_rewrite_scheduled成为0,并验证aof_last_bgrewrite_statusok.
  • 重新启动服务器后,检查您的数据库是否包含与之前包含的相同数量的键。

Redis 2.0 版本

  • 备份最新的 dump.rdb 文件。
  • 将此备份传输到安全的地方。
  • 停止对数据库的所有写入作!
  • 问题 aredis-cli BGREWRITEAOF.这将创建 append only 文件。
  • 在 Redis 完成生成 AOF 转储 后停止服务器。
  • edit redis.conf end enable append only file persistence.
  • 重新启动服务器。
  • 确保您的数据库包含的键数与切换前包含的键数相同。
  • 确保将写入正确附加到 append only 文件。

AOF 和 RDB 持久性之间的交互

Redis >= 2.4 确保在 RDB 快照作已在进行中,或者允许BGSAVE虽然 AOF 重写正在进行中。这可以防止两个 Redis 后台进程 避免同时执行繁重的磁盘 I/O。

当快照正在进行并且用户明确请求日志时 rewrite作使用BGREWRITEAOF服务器将回复 OK 状态代码告诉用户作已计划,并重写 将在快照完成后启动。

如果 AOF 和 RDB 持久性都已启用,并且 Redis 会重新启动 AOF 文件将用于重建原始数据集,因为它是 保证是最完整的。

备份 Redis 数据

在开始本节之前,请务必阅读以下句子:确保备份您的数据库。磁盘损坏、云中的实例消失等等:没有备份意味着数据消失到 /dev/null 中的巨大风险。

Redis 对数据备份非常友好,因为您可以复制 RDB 文件,而 数据库正在运行:RDB 一旦生成,就永远不会被修改,并且当 RDB 生成它时使用临时名称并重命名为其最终目标 仅当新快照完成时,才以原子方式使用 rename(2)。

这意味着,当服务器处于 运行。以下是我们的建议:

  • 在服务器中创建 cron 作业,在一个目录中创建 RDB 文件的每小时快照,并在另一个目录中创建每日快照。
  • 每次运行 cron 脚本时,请确保调用find命令确保删除太旧的快照:例如,您可以每小时拍摄最近 48 小时的快照,以及一两个月的每日快照。确保使用日期和时间信息命名快照。
  • 确保每天至少传输一次 RDB 快照,或者至少将 RDB 快照传输到运行 Redis 实例的物理机之外

备份 AOF 持久化

如果您运行的 Redis 实例仅启用了 AOF 持久性,您仍然可以执行备份。 从 Redis 7.0.0 开始,AOF 文件被拆分为多个文件,这些文件位于一个目录中,由appenddirname配置。 在正常作期间,您需要做的就是复制/tar 此目录中的文件以实现备份。但是,如果在重写期间执行此作,则最终可能会得到无效的备份。 要解决此问题,您必须在备份期间禁用 AOF 重写:

  1. 关闭自动重写
    CONFIG SET auto-aof-rewrite-percentage 0
    确保您没有手动启动重写(使用BGREWRITEAOF) 在此期间。
  2. 使用
    INFO persistence
    并验证aof_rewrite_in_progress为 0。如果为 1,则需要等待重写完成。
  3. 现在,您可以安全地复制appenddirname目录。
  4. 完成后重新启用重写:
    CONFIG SET auto-aof-rewrite-percentage <prev-value>

注意:如果要最大限度地减少禁用 AOF 重写的时间,您可以在appenddirname(在上面的步骤 3 中),然后在创建硬链接后重新启用重写(步骤 4)。 现在你可以复制/tar 硬链接并在完成后删除它们。这之所以有效,是因为 Redis 保证它 仅附加到此目录中的文件,或在必要时完全替换它们,因此内容应该是 在任何给定的时间点保持一致。

注意:如果您想处理服务器在备份期间重新启动的情况,并确保重新启动后不会自动开始重写,您可以更改上面的步骤 1 以同时通过CONFIG REWRITE. 只需确保在完成后重新启用自动重写(第 4 步)并使用另一个CONFIG REWRITE.

在版本 7.0.0 之前,只需复制 aof 文件(如备份 RDB 快照)即可备份 AOF 文件。文件可能缺少最终部分 但 Redis 仍然能够加载它(请参阅前面有关截断的 AOF 文件的部分)。

灾难恢复

Redis 上下文中的灾难恢复与 备份,以及在许多不同的外部传输这些备份的能力 数据中心。这样,即使在发生一些灾难性事件的情况下,数据也可以得到保护 事件影响 Redis 运行的主数据中心并生成其 快照。

我们将回顾最有趣的灾难恢复技术 没有太高的成本。

  • Amazon S3 和其他类似服务是实施灾难恢复系统的好方法。只需以加密形式将您的每日或每小时 RDB 快照传输到 S3 即可。您可以使用gpg -c(在对称加密模式下)。确保将密码存储在许多不同的安全位置(例如,将副本提供给组织中最重要的人员)。建议使用多个存储服务以提高数据安全性。
  • 使用 SCP(SSH 的一部分)将快照传输到远距离服务器。这是一个相当简单和安全的路线:在离你很远的地方买一个小型 VPS,在那里安装 ssh,并生成一个没有密码的 ssh 客户端密钥,然后将其添加到authorized_keys文件。您已准备好以自动方式传输备份。在两个不同的提供商处获得至少两个 VPS 以获得最佳效果。

重要的是要了解,否则此系统很容易失败 以正确的方式实施。至少,要绝对确保在 传输完成后,您可以验证文件大小(应匹配 您复制的文件之一)以及可能的 SHA1 摘要(如果您使用的是 一个 VPS。

您还需要某种独立的警报系统,如果 由于某种原因,备份无法正常工作。

为本页评分
返回顶部 ↑