Redis 数据备份 RDB

RDB

RDB 的优点

  • RDB 文件非常紧凑,适合作为冷备。比如你可以在每个小时报保存一下过去 24 小时内的数据,同时每天保存过去 30 天的数据,这样即使出了问题你也可以根据需求恢复到不同版本的数据集。
  • 快照在保存 RDB 文件时父进程唯一需要做的就是 fork 出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他 IO 操作,所以快照持久化方式可以最大化 Redis 的性能。
  • 恢复大数据集时,RDB 比 AOF 更快

RDB 的缺点

  • 如果系统发生故障,将会丢失最后一次创建快照之后的数据。如果你希望在 Redis 意外停止工作(例如电源中断)的情况下丢失的数据最少的话,那么 快照不适合你。虽然你可以配置不同的 save 时间点(例如每隔 5 分钟并且对数据集有 100 个写的操作),是 Redis 要完整的保存整个数据集是一个比较繁重的工作,你通常会每隔 5 分钟或者更久做一次完整的保存,万一在 Redis 意外宕机,你可能会丢失几分钟的数据。
  • 如果数据量很大,保存快照的时间会很长。快照需要经常 fork 子进程来保存数据集到硬盘上。当数据集比较大的时候,fork 的过程是非常耗时的,可能会导致 Redis 在一些毫秒级内不能响应客户端的请求。如果数据集巨大并且 CPU 性能不是很好的情况下,这种情况会持续 1 秒。AOF 也需要 fork,但是你可以调节重写日志文件的频率来提高数据集的耐久度。

RDB 的载入

RDB 文件的载入工作是在服务器启动时自动执行的,Redis 并没有专门用于载入 RDB 文件的命令。

服务器载入 RDB 文件期间,会一直处于阻塞状态,直到载入完成为止。

🔔 注意:因为 AOF 通常更新频率比 RDB 高,所以丢失数据相对更少。基于这个原因,Redis 有以下默认行为:

  • 只有在关闭 AOF 功能的情况下,才会使用 RDB 还原数据,否则优先使用 AOF 文件来还原数据。

Redis 的配置文件 redis.conf 中与 RDB 有关的选项:

  • save - Redis 会根据 save 选项,让服务器每隔一段时间自动执行一次 BGSAVE 命令。

  • stop-writes-on-bgsave-error - 当 BGSAVE 命令出现错误时停止写 RDB 文件

  • rdbcompression - RDB 文件开启压缩功能。

  • rdbchecksum - 对 RDB 文件进行校验。

  • dbfilename - RDB 文件名。

  • dir - RDB 文件和 AOF 文件的存储路径。

AOF

AOF 的优点

  • 如果系统发生故障,AOF 丢失数据比 RDB 少。你可以使用不同的 fsync 策略:无 fsync;每秒 fsync;每次写的时候 fsync。使用默认的每秒 fsync 策略,Redis 的性能依然很好(fsync 是由后台线程进行处理的,主线程会尽力处理客户端请求),一旦出现故障,你最多丢失 1 秒的数据。
  • AOF 文件可修复 - AOF 文件是一个只进行追加的日志文件,所以不需要写入 seek,即使由于某些原因(磁盘空间已满,写的过程中宕机等等)未执行完整的写入命令,你也也可使用 redis-check-aof 工具修复这些问题。
  • AOF 文件可压缩。Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写:重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。整个重写操作是绝对安全的,因为 Redis 在创建新 AOF 文件的过程中,会继续将命令追加到现有的 AOF 文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。而一旦新 AOF 文件创建完毕,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作。
  • AOF 文件可读 - AOF 文件有序地保存了对数据库执行的所有写入操作,这些写入操作以 Redis 命令的格式保存。因此 AOF 文件的内容非常容易被人读懂,对文件进行分析(parse)也很轻松。 导出(export) AOF 文件也非常简单。举个例子,如果你不小心执行了 FLUSHALL 命令,但只要 AOF 文件未被重写,那么只要停止服务器,移除 AOF 文件末尾的 FLUSHALL 命令,并重启 Redis ,就可以将数据集恢复到 FLUSHALL 执行之前的状态。

AOF 的缺点

  • AOF 文件体积一般比 RDB 大 - 对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。
  • 恢复大数据集时,AOF 比 RDB 慢。 - 根据所使用的 fsync 策略,AOF 的速度可能会慢于快照。在一般情况下,每秒 fsync 的性能依然非常高,而关闭 fsync 可以让 AOF 的速度和快照一样快,即使在高负荷之下也是如此。不过在处理巨大的写入载入时,快照可以提供更有保证的最大延迟时间(latency)。

appendfsync 不同选项决定了不同的持久化行为:

  • always - 将缓冲区所有内容写入并同步到 AOF 文件。
  • everysec - 将缓冲区所有内容写入到 AOF 文件,如果上次同步 AOF 文件的时间距离现在超过一秒钟,那么再次对 AOF 文件进行同步,这个同步操作是有一个线程专门负责执行的。
  • no - 将缓冲区所有内容写入到 AOF 文件,但并不对 AOF 文件进行同步,何时同步由操作系统决定。

AOF 的载入

因为 AOF 文件中包含了重建数据库所需的所有写命令,所以服务器只要载入并执行一遍 AOF 文件中保存的写命令,就可以还原服务器关闭前的数据库状态。

AOF 载入过程如下:

  1. 服务器启动载入程序。
  2. 创建一个伪客户端。因为 Redis 命令只能在客户端上下文中执行,所以需要创建一个伪客户端来载入、执行 AOF 文件中记录的命令。
  3. 从 AOF 文件中分析并读取一条写命令。
  4. 使用伪客户端执行写命令。
  5. 循环执行步骤 3、4,直到所有写命令都被处理完毕为止。
  6. 载入完毕。

AOF 的重写

随着 Redis 不断运行,AOF 的体积也会不断增长,这将导致两个问题:

  • AOF 耗尽磁盘可用空间。
  • Redis 重启后需要执行 AOF 文件记录的所有写命令来还原数据集,如果 AOF 过大,则还原操作执行的时间就会非常长。

为了解决 AOF 体积膨胀问题,Redis 提供了 AOF 重写功能,来对 AOF 文件进行压缩。AOF 重写可以产生一个新的 AOF 文件,这个新的 AOF 文件和原来的 AOF 文件所保存的数据库状态一致,但体积更小

AOF 重写并非读取和分析现有 AOF 文件的内容,而是直接从数据库中读取当前的数据库状态。即依次读取数据库中的每个键值对,然后用一条命令去记录该键值对,以此代替之前可能存在冗余的命令。

AOF 后台重写

作为一种辅助性功能,显然 Redis 并不想在 AOF 重写时阻塞 Redis 服务接收其他命令。因此,Redis 决定通过 BGREWRITEAOF 命令创建一个子进程,然后由子进程负责对 AOF 文件进行重写,这与 BGSAVE 原理类似。

  • 在执行 BGREWRITEAOF 命令时,Redis 服务器会维护一个 AOF 重写缓冲区。当 AOF 重写子进程开始工作后,Redis 每执行完一个写命令,会同时将这个命令发送给 AOF 缓冲区和 AOF 重写缓冲区。
  • 由于彼此不是在同一个进程中工作,AOF 重写不影响 AOF 写入和同步。当子进程完成创建新 AOF 文件的工作之后,服务器会将重写缓冲区中的所有内容追加到新 AOF 文件的末尾,使得新旧两个 AOF 文件所保存的数据库状态一致。
  • 最后,服务器用新的 AOF 文件替换就的 AOF 文件,以此来完成 AOF 重写操作。

img

可以通过设置 auto-aof-rewrite-percentageauto-aof-rewrite-min-size,使得 Redis 在满足条件时,自动执行 BGREWRITEAOF

假设配置如下:

1
2
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

表明,当 AOF 大于 64MB,且 AOF 体积比上一次重写后的体积大了至少 100% 时,执行 BGREWRITEAOF

AOF 的配置

AOF 的默认配置:

1
2
3
4
5
appendonly no
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

AOF 持久化通过在 redis.conf 中的 appendonly yes 配置选项来开启。

  • appendonly - 开启 AOF 功能。
  • appendfilename - AOF 文件名。
  • appendfsync - 用于设置同步频率,它有以下可选项:
    • always - 每个 Redis 写命令都要同步写入硬盘。这样做会严重降低 Redis 的速度。
    • everysec - 每秒执行一次同步,显示地将多个写命令同步到硬盘。为了兼顾数据安全和写入性能,推荐使用 appendfsync everysec 选项。Redis 每秒同步一次 AOF 文件时的性能和不使用任何持久化特性时的性能相差无几。
    • no - 让操作系统来决定应该何时进行同步。
  • no-appendfsync-on-rewrite - AOF 重写时不支持追加命令。
  • auto-aof-rewrite-percentage - AOF 重写百分比。
  • auto-aof-rewrite-min-size - AOF 重写文件的最小大小。
  • dir - RDB 文件和 AOF 文件的存储路径。