在实际生产中,无论我们多么地小心,意外总是会发生。很多意外是不可控的,如机房停电等。我们该如何备份 Redis 数据,并在遇到意外时把它恢复出来呢?

备份 Redis 数据

在开始介绍前,请提醒自己:一定要备份数据库!

磁盘是会损坏的,云端的实例是会销毁的,因此:没有备份就意味着要承担数据消失在 /dev/null 中的高风险。

备份 RDB

Redis 对于数据备份非常友好,即使在它运行的时候,你也可以拷贝数据库文件。这是因为 RDB 文件一旦生成后就不会再修改,即使修改,它也会使用一个临时文件,并且仅在新的快照写完后,才会自动重命名新快照为“旧文件名”。

这意味着在 Redis 运行时 拷贝 RDB 文件是完全安全的。我们建议你这样做:

  • 在你的 server 上创建一个定时任务:每小时生成一个快照,存放到某个目录中;每天也生成一个快照,存放在另一个目录中。
  • 每当定时任务运行的时候,使用 find 来确保删除了过时的快照。比如说,你可以删除 48 小时前的每小时快照,也可以删除一两个月前的每日快照。使用日期和时间来命名你的快照,这样容易区分。
  • 把 RDB 镜像传输到数据中心以外的地方,至少也要传输到运行 Redis 实例的机器外,最少每天做一次。

备份 AOF

如果你运行的 Redis 实例已经开启了 AOF,你仍然可以完成备份。

Redis 版本 >= 7.0.0

单个 AOF 文件被分为了多个文件,它们存放在同一个目录中,目录名和配置中的 appenddirname 值保持一致。在正常操作中,你只需要拷贝/归档这个目录下的文件就好了。

不过,如果你是在日志重写时操作,你可能会得到一个无效的备份。为了解决这个问题,你必须在备份时禁用 AOF 重写:

  1. 关闭自动重写:CONFIG SET auto-aof-rewrite-percentage 0,同时不要使用 BGREWRITEAOF 命令手动开始重写。
  2. 检查是否正在进行的重写:INFO persistence,确保 aof_rewrite_in_progress 的值为 0。如果它是 1 的话,你就不得不等待重写完成后再备份了。
  3. 现在你就可以安全地拷贝 appenddirname 目录的文件了。
  4. 当备份完成后,重新开启 AOF:CONFIG SET auto-aof-rewrite-percentage <prev-value>

Redis 版本 < 7.0.0

由于所有的日志都在同一个 AOF 文件中,只需要把这个 AOF 文件拷贝一份就好了(就像备份 RDB 那样)。

这个 AOF 文件可能缺少最后的部分,但是 Redis 仍能正常加载它(参见上一篇文章的 AOF 截断 部分)。

操作步骤如下:

  1. 关闭自动重写:CONFIG SET auto-aof-rewrite-percentage 0,同时不要使用 BGREWRITEAOF 命令手动开始重写。
  2. 检查是否正在进行的重写:INFO persistence,确保 aof_rewrite_in_progress 的值为 0。如果它是 1 的话,你就不得不等待重写完成后再备份了。
  3. 现在你就可以安全地拷贝 appenddirname 目录的文件了。
  4. 当备份完成后,重新开启 AOF:CONFIG SET auto-aof-rewrite-percentage <prev-value>

灾备恢复

就 Redis 而言,灾难恢复基本上和备份是一样的,只不过是多了一步:把这些备份文件传输到许多不同的外部数据中心而已。

这样一来,即使是 Redis 在上面运行和生成快照的主数据中心发生故障,数据也仍然是安全的。

我们来看看最有意思的灾备恢复技巧,它不需要很高的投入:

  • Amazon S3 和其他类似的服务是实现灾备系统的很好的方式。你只要把你的每日快照或每小时快照加密传输到 S3 上,你可以使用 gpg -c(对称加密)。请确保你在多处另存了这个密码(比如把这个密码分享给你最重要的组织成员)。推荐多用几个存储服务,进一步提升数据安全性。
  • 使用 SCP(它包含在 SSH 里)来传输快照到远端的服务器上。这样做既简单又安全:租一台距离你很远的小型 VPS,为它安装 ssh,然后在你自己的机器上生成一个不带密码短语passphrase的 ssh 客户端密钥,最后把它添加到 VPS 的 authorized_keys 文件中。如此操作后,你就可以实现自动传输备份到 VPS 上了。推荐你租用至少两台不同提供商的 VPS,这样更安全。

有一件很重要的事情,那就是请确保在传输完成之后校验文件的大小(它应该和你拷贝的文件一致)。如果你使用 VPS 的话,最好再校验一下 SHA1。

同时,你还需要有个独立的告警系统,以在最新的备份传输失败的时候,得到及时的提醒。

后语

本文是「Redis 持久化」系列的最后一篇文章,如果可能的话,下一个系列将会是~「Redis 复制」~「Redis 使用」。保持关注喔!

参考


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