Redis MIGRATE 命令将 redis 中的 key 原子性地从当前实例传送(迁移)到目标实例的指定数据库上,一旦传送成功,相应的 key 保证会出现在目标实例上,而当前实例上的 key 会被删除。
命令格式
MIGRATE host port key|"" destination-db timeout [COPY] [REPLACE] [KEYS key [key ...]]
可用版本:>=2.6.0
时间复杂度:这个命令在源实例上实际执行 DUMP 命令和 DEL 命令,在目标实例上执行 RESTORE 命令,查看以上命令的文档可以看到详细的复杂度说明。key 数据在两个实例之间传输的复杂度为 O(n)。
MIGRATE 命令是一个原子操作,它在执行的时候会阻塞进行迁移的两个实例,直到以下任意结果发生:
- 迁移成功
- 迁移失败
- 等待超时
MIGRATE 命令的内部实现是这样的,主要分为 3 个步骤:
- 它在当前实例对给定 key 执行 DUMP 命令,将它序列化,然后传送到目标实例;
- 目标实例再使用 RESTORE 对数据进行反序列化,并将反序列化所得的数据添加到数据库中;
- 当前实例就像目标实例的客户端那样,只要看到 RESTORE 命令返回 OK,它就会调用 DEL 命令删除自己数据库上的 key。
MIGRATE 命令需要在给定的时间规定内完成 IO 操作。如果在传送数据时发生 IO 错误,或者达到了超时时间,那么命令会停止执行,并返回一个特殊的错误 IO ERR。
当 IO ERR 出现时,有以下 2 种可能:
- key 可能存在于两个实例。
- key 可能只存在于当前实例。
唯一不可能发生的情况就是丢失 key,因此,如果一个客户端执行 MIGRATE 命令,并且不幸遇上 IO ERR 错误,那么这个客户端唯一要做的就是检查自己数据库上的 key 是否已经被正确地删除。
如果有其他错误发生,那么 MIGRATE 保证 key 只会出现在当前实例中(当然,目标实例的给定数据库上可能有和 key 同名的键,不过这和 MIGRATE 命令没有关系)。
命令参数
- host:目标实例的 host。
- port:目标实例的端口号。
- key|"":传具体 key 表示迁移该 key;在 3.2 及更高版本中,可以结合空字符串("")和 KEYS 子句来指定要迁移的 key,并可以在 MIGRATE 的单个调用中对多个 key 进行流水线处理。
- destination-db:目标实例的数据库。
- timeout:指定当前实例和目标实例进行沟通的最大间隔时间,单位为毫秒。这说明操作并不一定要在 timeout 内完成,只是说数据传送的时间不能超过这个 timeout 值。
- COPY:不移除源实例上的 key,3.0 及更高版本开始可用。
- REPLACE:替换目标实例上已存在的 key,3.0 及更高版本开始可用。
- KEYS 子句:如果 key 参数是一个空字符串,该命令将改为迁移遵循 KEYS 选项的所有键,参照如上 key|"" 的说明。3.0.6 及更高版本开始可用。
从 Redis 3.0.6开始,MIGRATE 支持新的批量迁移模式,该模式使用 pipeline 操作以在实例之间迁移多个 key,而不会产生往返时间延迟以及使用单个 MIGRATE 调用迁移每个 key 时的其他开销。
为了启用该功能,使用 KEYS 选项,并将普通键参数设置为空字符串。实际的键名将在 KEYS 参数后面提供。
命令返回值
MIGRATE 命令返回有 2 种情况:
- 返回 OK,当迁移成功时。
- 返回 NOKEY,如果在源实例中没有要迁移的 key,如 key 过期了,所以 NOKEY 不是一个错误。
示例
127.0.0.1:6379> SET mgr test
OK
127.0.0.1:6379> SET mgr1 test1
OK
127.0.0.1:6379> MIGRATE 127.0.0.1 6380 "" 0 2000 COPY KEYS mgr mgr1 # 批量迁移key
OK
127.0.0.1:6380> GET mgr
"test"
127.0.0.1:6380> GET mgr1
"test1"
127.0.0.1:6379> SET mgr1 test_replace
OK
127.0.0.1:6379> MIGRATE 127.0.0.1 6380 mgr1 0 2000 COPY REPLACE # 单个key迁移且替换目标已存在的key
OK
127.0.0.1:6380> GET mgr1
"test_replace"
127.0.0.1:6379> MIGRATE 127.0.0.1 6380 mgr_nokey 0 2000 COPY # 迁移不存在的key,返回NOKEY
NOKEY
Redis 键迁移
想将一个 Redis 的数据迁移到另一个 Redis 中,Redis 提供了三种方式来满足数据迁移的需求:
- MOVE
- DUMP+RESTORE
- MIGRATE
MOVE 命令
Redis 支持多数据库,多数据库之间彼此在数据上是隔离的。move key db 就是把指定的键从源数据库迁移到目标数据库中。由于多数据库在生产环境中不建议使用,所以此命令很少使用到。MOVE 命令的更详细内容,参考 Redis MOVE 命令。
DUMP+RESTORE 命令
DUMP+RESTORE 可以实现 Redis 不同实例之间的数据迁移。
- 在源 Redis 上,DUMP 命令会将键值序列化,格式采用 RDB 格式。
- 在目标 Redis 上,RESTORE 命令会将上面序列化的值进行复原,其中 ttl 代表过期时间,如果 ttl 为0,则表示没有过期时间。
整个迁移过程并非原子性的,而是通过客户端分布完成的。
迁移过程是开启了两个实例的 Redis 客户端,将源 Redis 序列化后的值放到目标 Redis 实例客户端进行操作,并不是在源 Redis 和目标 Redis 之间进行传输。