我有两个 Redis 实例(或两个各自的 dump.rdb 文件),我想将它们组合成一个具有两个数据库的实例,每个实例对应一个单独的初始实例。
我可以使用 MEGG 来执行此操作,但它仅在 Redis 2.6.0 中可用,我当前的 Redis 服务器不支持该版本。
编辑
对于较新版本的 redis 来说,这个答案不再准确。由于历史原因留下答案。
如果您愿意尝试使用二进制文件,则可以轻松地将两个dump.rdb文件合并为一个。
假设:
- 每个转储只有一个数据库 - 默认数据库
- 您使用的是 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文件,请执行以下操作-
- 创建新的目标文件
- 复制第一个文件中除最后一个文件之外的所有内容
FF
FE 01
复制两个字节以指示第二个数据库的开始- 注意:如果您确定两个数据库没有重复的键,并且希望将它们合并到一个数据库中,只需跳过上面提到的两个字节
FE 01
。 - 从第二个文件中,跳过前 11 个字节 - 即跳过
REDIS000x FE 00
- 复制第二个文件的其余部分,包括最后一个字节
FF
您现在可以将此新的 dump.rdb 复制到 redis 中的相应目录并重新启动。
如果您有兴趣,这里有 redis 转储文件格式的完整文档,但对于这个简单的用例,您不需要了解所有文档。
以下是我用来将 4 个 Redis 服务器(运行 2.4.x)合并为 2 个(我两次将 2 个单独的 Redis 实例(每个实例的数据在 db0 中)合并为 1 个包含两个独立数据库的技术:
- 使新实例 Foo 成为实例 A 的从属实例(即编辑
redis.conf
并使用slaveof
)。 - 一旦Foo完成从A的同步,删除slaveof,这样它就成为主节点。所有数据都将以 db0 为单位。
- 使用 redis-dump(Ruby 库,但具有命令行实用程序)从实例 B 导出或转储所有数据。这将创建一个 JSON 文件。
- 如果数据位于实例 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
- 使用 redis-dump 的
redis-load
命令将包含实例 B 中的数据的 JSON 文件导入到 Foo 中。- 如果您编辑了 JSON 文件并更改了数据库,以便使用其他内容(例如 3),则需要将数据导入该数据库,即
<new.json redis-load -u host:port -d 3
- 如果您有足够的数据(我正在导入 GB),则可能需要数小时。您可以通过在与目标 Redis 实例 (Foo) 相同的机器上运行此过程来加快速度。
- 如果您编辑了 JSON 文件并更改了数据库,以便使用其他内容(例如 3),则需要将数据导入该数据库,即
现在,您有一个 Redis 实例 (Foo),其中 A 的数据在 db0 中,B 的数据在 db1 中。
我遇到了很多麻烦,所以我创建了一个使用转储和恢复的 python 脚本。它将一个 db 序列化为字典对象并对其进行描绘。使用不同的开关加载图片文件,并将数据上传到其他 redis 实例。
https://gist.github.com/romanmah/9664407