将两个 Redis 实例合并为一个具有两个数据库的实例



我有两个 Redis 实例(或两个各自的 dump.rdb 文件),我想将它们组合成一个具有两个数据库的实例,每个实例对应一个单独的初始实例。

我可以使用 MEGG 来执行此操作,但它仅在 Redis 2.6.0 中可用,我当前的 Redis 服务器不支持该版本。

编辑

对于较新版本的 redis 来说,这个答案不再准确。由于历史原因留下答案。


如果您愿意尝试使用二进制文件,则可以轻松地将两个dump.rdb文件合并为一个。

假设:

  1. 每个转储只有一个数据库 - 默认数据库
  2. 您使用的是 Redis 2.4.x,因此转储版本为 2 或 3

如果在十六进制编辑器中打开文件,则这是 RDB 文件的格式 -

REDIS000x FE 00 <actual data > FF

这里-

  • 000x是 RDB 版本号。在您的情况下,很可能是 0002 或 0003
  • FE 是数据库选择器,00是数据库编号
  • <actual data>是当前数据库中的键值对。对于当前目的,可以将其视为二进制 blob。
  • FF 是文件中的最后一个字节,表示 rdb 文件的结尾

因此,要合并两个rdb文件,请执行以下操作-

  1. 创建新的目标文件
  2. 复制第一个文件中除最后一个文件之外的所有内容FF
  3. FE 01复制两个字节以指示第二个数据库的开始
  4. 注意:如果您确定两个数据库没有重复的键,并且希望将它们合并到一个数据库中,只需跳过上面提到的两个字节FE 01
  5. 从第二个文件中,跳过前 11 个字节 - 即跳过REDIS000x FE 00
  6. 复制第二个文件的其余部分,包括最后一个字节FF

您现在可以将此新的 dump.rdb 复制到 redis 中的相应目录并重新启动。

如果您有兴趣,这里有 redis 转储文件格式的完整文档,但对于这个简单的用例,您不需要了解所有文档。

以下是我用来将 4 个 Redis 服务器(运行 2.4.x)合并为 2 个(我两次将 2 个单独的 Redis 实例(每个实例的数据在 db0 中)合并为 1 个包含两个独立数据库的技术:

  1. 使新实例 Foo 成为实例 A 的从属实例(即编辑redis.conf并使用 slaveof )。
  2. 一旦Foo完成从A的同步,删除slaveof,这样它就成为主节点。所有数据都将以 db0 为单位。
  3. 使用 redis-dump(Ruby 库,但具有命令行实用程序)从实例 B 导出或转储所有数据。这将创建一个 JSON 文件。
  4. 如果数据位于实例 B 的 db0 中,那么您现在需要编辑步骤 #3 中生成的 JSON 文件。这是您不希望将 B 的数据导入 Foo 的 db0 的 b/c,该数据库现在包含 A 的数据。
    • Redis-dump 的格式包含每个键的源数据库;因此,您需要编辑文档以将 db 从 0 更改为其他内容 - 1、2 等。
    • 我的 JSON 文件很大,所以我使用 sed: sed -e 's/"db":0/"db":3/' orig.json > db_3.json
  5. 使用 redis-dump 的 redis-load 命令将包含实例 B 中的数据的 JSON 文件导入到 Foo 中。
    • 如果您编辑了 JSON 文件并更改了数据库,以便使用其他内容(例如 3),则需要将数据导入该数据库,即<new.json redis-load -u host:port -d 3
    • 如果您有足够的数据(我正在导入 GB),则可能需要数小时。您可以通过在与目标 Redis 实例 (Foo) 相同的机器上运行此过程来加快速度。

现在,您有一个 Redis 实例 (Foo),其中 A 的数据在 db0 中,B 的数据在 db1 中。

我遇到了很多麻烦,所以我创建了一个使用转储和恢复的 python 脚本。它将一个 db 序列化为字典对象并对其进行描绘。使用不同的开关加载图片文件,并将数据上传到其他 redis 实例。

https://gist.github.com/romanmah/9664407

最新更新