Redis 往磁盘里写入数据(持久化)的方式,包括了“仅追加文件”(AOF)和“快照”(RDB)两种,让我们一起来看看它们的优点与缺点吧!

前言

持久化就是指把数据写入到一个持久的存储设备(例如固态硬盘)中。

Redis 提供了一系列持久化选项:

  • RDB(Redis Database):经过指定的时间间隔,自动生成该时间点的数据集快照。
  • AOF(Append Only File):记录每一个 server 收到的写操作到一个日志文件中。每当 server 重新启动时,它都会重放这些操作来恢复原始数据集。写操作使用 Redis 协议的格式保存,仅追加文件。当这个日志文件变得太大时,server 可以在后台重写它。
  • No persistence:不配置持久化,数据仅在 server 运行时存在于内存中,server 停止运行后数据消失。
  • RDB + AOF:可以在同一个 server 实例中,同时使用 AOF 和 RDB 这两种持久化方式。需要注意的是,当 server 重新启动时,它将使用 AOF 文件来恢复原始数据集,因为它是最完整的。

然而,最重要的是理解 RDB 和 AOF 这两种持久化方式各有什么优缺点。

RDB 优点

  • RDB 把 server 中的数据保存在一个紧凑的文件中,它很适合用于备份。例如,你可能会想要每隔一个小时都备份一次过去 24 小时的数据,或者每隔一天备份一次过去 30 天的数据。当灾难来临时,RDB 使你可以很轻松地恢复不同版本的数据集。
  • RDB 非常适合灾备恢复,它是一个单文件,可以在相距很远的数据中心之间转移。
  • RDB 几乎不会影响 server 的性能,因为 server 进程唯一需要做的事就是 fork 一个子进程,然后让子进程完成剩下的所有工作,server 进程不会参与任何的磁盘 I/O。
  • 如果重启时要恢复一个很大的数据集,那么与 AOF 相比,RDB 会快很多。
  • 复制时,如果出现重启或者失败的情况,RDB 支持重新同步部分的数据。

RDB 缺点

  • 如果你想要追求最少的数据损失(比方说在一次停电后),那么 RDB 不适合你。你可以设置不同的保存点(比如每隔 5 分钟 或者每写入 100 次),你可以同时设置多个保存点。然而,一般都是设置在 5 分钟以上,因此如果 server 没有正常停止的话,你要做好丢失最近几分钟数据的准备。
  • RDB 需要经常调用 fork() 生成子进程来进行持久化工作。然而,如果需要持久化的数据集很大的话,执行 fork() 需要耗费大量的时间。如果数据集非常大,并且服务器的 CPU 不大给力的话,这还可能会导致 server 在数个毫秒甚至一秒内暂停接受 client 请求。AOF 也需要 fork(),但是要不频繁一些,而且它还支持让你在不损失数据的持久型的前提下,修改重写日志的频率。

AOF 优点

  • 使用 AOF 可以让 server 的持久化程度更高,因为它支持不同的 fsync 策略。比如说:禁用 fsync、每秒钟执行一次 fsync、每次查询执行一次 fsync 等。默认的策略是每秒钟执行一次 fsync,即使这样,性能仍然很棒。fsync 是在后台线程执行的,在不执行 fsync 时,主线程会尽全力去执行写操作。这样一来,即使发生故障,你最多也只会丢失一秒钟的数据而已。
  • AOF 日志文件是一个仅追加的文件,所以它不需要执行查找,断电时也没有崩溃问题。即使最后一条命令只写了一半(由于磁盘写满了或其他原因),redis-check-aof 工具也可以轻松修复这个 AOF 日志文件。
  • 当 AOF 变得太大了时,server 可以自动在后台重写它。重写操作是非常安全的,因为在 server 持续追加命令到旧文件时,新的文件会被同时创建。server 会对这个新的文件进行一些设置,一旦完成,server 就会开始追加命令到新的文件中。
  • AOF 一条条地记录了所有的操作,记录的格式是非常容易理解和解析的。你甚至可以很轻松地导出一个 AOF 文件。比如说,即使你意外地使用 FLUSHALL 命令覆盖了所有的数据,只要这时候没有进行 AOF 重写,你都可以恢复你的数据。你只需要停止 server,删除最近的一条命令,然后重启 server 就好了。

AOF 缺点

  • 对于同一个数据集,AOF 文件通常会比 RDB 文件要占用更多的空间。
  • 取决于不同的 fsync 策略,AOF 可能会比 RDB 要慢。通常来说,每秒钟执行一次 fsync,性能仍然很棒;禁用 fsync 后,即使在高负载下,性能也应该和 RDB 差不多。不过,RDB 仍然在能够保证在写负载很大的情况下,提供(较小)最大延时的保证,这是 AOF 做不到的。

对于 Redis 7.0 以下版本,AOF 还有下面这几个缺点:

  • 在一次重写中,如果 server 同时接受了写操作,那么 AOF 会占用大量的内存(因为这些写操作会缓存在内存里,最后才会写入到新的 AOF 文件中)。
  • 所有在执行重写时到达 server 的写操作,都会被重复写入一次磁盘。
  • 在重写结束时,server 会把写入操作追加到新的 AOF 文件中,在这期间,server 可能会停止写入内存数据。

后语

下一篇文章,我将介绍如何选用 Redis 的这两种持久化方式(RDB 和 AOF)以及它们的工作原理。保持关注喔!

参考

  • [Redis Documentation - Redis persistence][2]

本文使用 CC BY-SA 4.0 国际协议 进行许可,欢迎 遵照协议规定 转载。
作者:六开箱
链接:https://lkxed.github.io/posts/redis-persistence-pros-cons/