槽管理命令
本节将对 CLUSTER 命令中与槽管理有关的命令,如 CLUSTER SLOTS、CLUSTER ADDSLOTS、CLUSTER FLUSHSLOTS 等进行介绍。
CLUSTER SLOTS:查看槽与节点之间的关联信息
用户可以通过执行以下命令,获知各个槽与集群节点之间的关联信息:
CLUSTER SLOTS
命令会返回一个嵌套数组,数组中的每个项记录了一个槽范围(slot range)及其处理者的相关信息,其中包括:
-
槽范围的起始槽。
-
槽范围的结束槽。
-
负责处理这些槽的主节点信息。
-
零个或任意多个主节点属下从节点的信息。
其中,每一项节点信息都由以下 3 项信息组成:
-
节点的 IP 地址。
-
节点的端口号。
-
节点的运行 ID。
以下是一个 CLUSTER SLOTS 命令的执行示例:
127.0.0.1:30001> CLUSTER SLOTS
1) 1) (integer) 0 --起始槽
2) (integer) 5460 --结束槽
3) 1) "127.0.0.1" --主节点信息
2) (integer) 30001
3) "9e2ee45f2a78b0d5ab65cbc0c97d40262b47159f"
4) 1) "127.0.0.1" --从节点信息
2) (integer) 30005
3) "f584b888fcc0e7648bd838cb3b0e2d1915ac0ad7"
2) 1) (integer) 10923
2) (integer) 16383
3) 1) "127.0.0.1"
2) (integer) 30003
3) "a80b64eedcd15329bc0dc7b71652ecddccf6afe8"
4) 1) "127.0.0.1"
2) (integer) 30004
3) "ab0b79f233efa0afa467d9ef1700fe5b24154992"
3) 1) (integer) 5461
2) (integer) 10922
3) 1) "127.0.0.1"
2) (integer) 30002
3) "b2c7a5ca5fa6de72ac2842a2196ab2f4a5c82a6a"
4) 1) "127.0.0.1"
2) (integer) 30006
3) "262acdf22f4adb6a20b8116982f2940890693d0b"
从命令的结果可以看出:
-
集群的所有槽被划分成了 3 个槽范围,分别是 0~5460、5461~10922 和 10923~16383。
-
负责处理槽范围 0~5460 的主节点为 127.0.0.1:30001,它的运行 ID 为 "9e2ee45f2a78b0d5ab65cbc0c97d40262b47159f"。
-
主节点 30001 还有一个从节点 127.0.0.1:30005,它的运行 ID 为 "f584b888fcc0e7648bd838cb3b0e2d1915ac0ad7"。
除了槽范围 0~5460 之外,其余的两个槽范围也可以做类似的解读,此处不一一赘述。
版本较旧的 Redis 集群在执行 CLUSTER SLOTS 命令时只会返回节点的 IP 地址和端口号,不会返回节点的运行 ID。 |
其他信息
-
复杂度:O(N),其中 N 为集群中包括主节点和从节点在内的节点总数量。
-
版本要求:CLUSTER SLOTS 命令从 Redis 3.0.0 版本开始可用。
CLUSTER ADDSLOTS:把槽指派给节点
通过在节点上执行以下命令,我们可以将给定的一个或任意多个槽指派给当前节点进行处理:
CLUSTER ADDSLOTS slot [slot ...]
命令在成功执行指派操作之后将返回 OK 作为结果。
作为例子,以下代码演示了如何将尚未被指派的槽 0~5 指派给节点 30001 负责:
127.0.0.1:30001> CLUSTER ADDSLOTS 0 1 2 3 4 5
OK
我们可以通过执行 CLUSTER SLOTS 命令来确认这些槽已经被成功指派给了节点 30001:
127.0.0.1:30001> CLUSTER SLOTS
1) 1) (integer) 0
2) (integer) 5
3) 1) "127.0.0.1"
2) (integer) 30001
3) "9e2ee45f2a78b0d5ab65cbc0c97d40262b47159f"
...
需要注意的是,CLUSTER ADDSLOTS 只能对尚未被指派的槽执行指派操作,如果用户给定的槽已经被指派,那么命令将返回一个错误:
--尝试指派已被指派的槽,命令报错
127.0.0.1:30001> CLUSTER ADDSLOTS 0 1 2 3 4 5
(error) ERR Slot 0 is already busy
其他信息
-
复杂度:O(N),其中 N 为用户给定的槽数量。
-
版本要求:CLUSTER ADDSLOTS 命令从 Redis 3.0.0 版本开始可用。
CLUSTER DELSLOTS:撤销对节点的槽指派
在使用 CLUSTER ADDSLOTS 命令将槽指派给节点负责之后,用户可以在有需要的情况下,通过执行以下命令撤销对节点的槽指派:
CLUSTER DELSLOTS slot [slot ...]
命令在执行成功之后将返回 OK 作为结果。
作为例子,假设现在有槽配置如下:
--槽0~5由节点30001负责
--槽6~5460未指派
--槽5461~10922由节点30002负责
--槽10923~16383由节点30003负责
127.0.0.1:30001> CLUSTER SLOTS
1) 1) (integer) 0
2) (integer) 5
3) 1) "127.0.0.1"
2) (integer) 30001
3) "9e2ee45f2a78b0d5ab65cbc0c97d40262b47159f"
2) 1) (integer) 10923
2) (integer) 16383
3) 1) "127.0.0.1"
2) (integer) 30003
3) "a80b64eedcd15329bc0dc7b71652ecddccf6afe8"
3) 1) (integer) 5461
2) (integer) 10922
3) 1) "127.0.0.1"
2) (integer) 30002
3) "b2c7a5ca5fa6de72ac2842a2196ab2f4a5c82a6a"
那么我们可以通过对节点 30001 执行以下命令,撤销对该节点的槽 0~5 的指派:
127.0.0.1:30001> CLUSTER DELSLOTS 0 1 2 3 4 5
OK
通过再次执行 CLUSTER SLOTS 命令,我们可以确认槽 0~5 已经不再由节点 30001 负责,并且已经重新回到未指派状态:
--只有槽5461~16383被指派了,其他槽都处于未指派状态
127.0.0.1:30001> CLUSTER SLOTS
1) 1) (integer) 10923
2) (integer) 16383
3) 1) "127.0.0.1"
2) (integer) 30003
3) "a80b64eedcd15329bc0dc7b71652ecddccf6afe8"
2) 1) (integer) 5461
2) (integer) 10922
3) 1) "127.0.0.1"
2) (integer) 30002
3) "b2c7a5ca5fa6de72ac2842a2196ab2f4a5c82a6a"
需要注意的是,在执行 CLUSTER DELSLOTS 命令时,用户给定的必须是已经指派给当前节点的槽,尝试撤销一个未指派的槽将引发一个错误:
127.0.0.1:30001> CLUSTER DELSLOTS 0 1 2 3 4 5
(error) ERR Slot 0 is already unassigned
其他信息
-
复杂度:O(N),其中 N 为用户给定的槽数量。
-
版本要求:CLUSTER DELSLOTS 命令从 Redis 3.0.0 版本开始可用。
CLUSTER FLUSHSLOTS:撤销对节点的所有槽指派
通过在一个节点上执行以下命令,我们可以撤销对该节点的所有槽指派,让它不再负责处理任何槽:
CLUSTER FLUSHSLOTS
CLUSTER FLUSHSLOTS 命令在执行成功之后将返回 OK 作为结果,执行这个命令相当于对该节点负责的所有槽执行 CLUSTER DELSLOTS 命令。
举个例子,对于具有以下槽配置的集群来说:
--节点30001负责槽0~5460 ,节点30002负责槽5461~10922 ,节点30003负责槽10923~16383
127.0.0.1:30001> CLUSTER SLOTS
1) 1) (integer) 0
2) (integer) 5460
3) 1) "127.0.0.1"
2) (integer) 30001
3) "9e2ee45f2a78b0d5ab65cbc0c97d40262b47159f"
2) 1) (integer) 10923
2) (integer) 16383
3) 1) "127.0.0.1"
2) (integer) 30003
3) "a80b64eedcd15329bc0dc7b71652ecddccf6afe8"
3) 1) (integer) 5461
2) (integer) 10922
3) 1) "127.0.0.1"
2) (integer) 30002
3) "b2c7a5ca5fa6de72ac2842a2196ab2f4a5c82a6a"
如果我们对节点 30001 执行以下命令,那么该节点对于槽 0~5460 的指派将会被撤销:
127.0.0.1:30001> CLUSTER FLUSHSLOTS
OK
再次执行 CLUSTER SLOTS 命令可以看到,集群现在只有两个节点被指派了槽,而节点 30001 并不在此列:
--槽0~5460尚未被指派,节点30002负责槽5461~10922 ,节点30003负责槽10923~16383
127.0.0.1:30001> CLUSTER SLOTS
1) 1) (integer) 10923
2) (integer) 16383
3) 1) "127.0.0.1"
2) (integer) 30003
3) "a80b64eedcd15329bc0dc7b71652ecddccf6afe8"
2) 1) (integer) 5461
2) (integer) 10922
3) 1) "127.0.0.1"
2) (integer) 30002
3) "b2c7a5ca5fa6de72ac2842a2196ab2f4a5c82a6a"
需要注意的是,用户在执行 CLUSTER FLUSHSLOTS 命令之前,必须确保节点的数据库为空,否则节点将拒绝执行命令并返回一个错误:
--尝试对非空节点30002执行CLUSTER FLUSHSLOTS
127.0.0.1:30002> DBSIZE
(integer) 3
127.0.0.1:30002> CLUSTER FLUSHSLOTS
(error) ERR DB must be empty to perform CLUSTER FLUSHSLOTS.
其他信息
-
复杂度:O(N),其中 N 为节点被撤销指派的槽数量。
-
版本要求:CLUSTER FLUSHSLOTS 命令从 Redis 3.0.0 版本开始可用。
CLUSTER KEYSLOT:查看键所属的槽
通过对给定键执行以下命令,我们可以知道该键所属的槽:
CLUSTER KEYSLOT key
比如,如果我们想要知道 message 键以及 counter::12345 键属于哪个槽,那么可以执行以下命令:
127.0.0.1:30001> CLUSTER KEYSLOT message
(integer) 11537 -- message键属于槽11537
127.0.0.1:30001> CLUSTER KEYSLOT counter::12345
(integer) 12075 -- counter::12345键属于槽12075
最后,正如前文所说,带有相同散列标签的键将被分配到相同的槽中:
--两个带有相同散列标签{user}的键
127.0.0.1:30001> CLUSTER KEYSLOT {user}::256
(integer) 5474
127.0.0.1:30001> CLUSTER KEYSLOT {user}::10086
(integer) 5474
其他信息
-
复杂度:O(N),其中 N 为给定键的字节长度。
-
版本要求:CLUSTER KEYSLOT 命令从 Redis 3.0.0 版本开始可用。
CLUSTER COUNTKEYSINSLOT:查看槽包含的键数量
通过执行以下命令,用户可以查看给定槽包含的键数量:
CLUSTER COUNTKEYSINSLOT slot
举个例子,假如我们想要知道槽 523 包含了多少个键,那么只需要执行以下命令即可:
127.0.0.1:30001> CLUSTER COUNTKEYSINSLOT 523
(integer) 2
-
只对当前节点进行计数
用户在使用 CLUSTER COUNTKEYSINSLOT 命令时需要特别注意一点,即 CLUSTER COUNTKEYSINSLOT 命令只会在执行该命令的节点中进行计数:
如果执行命令的节点并不是负责处理给定槽的节点,那么命令将找不到任何属于给定槽的键。在这种情况下,命令只会单纯地返回 0 作为执行结果。
举个例子,如果我们对负责处理槽 0~5460 的节点 30001 执行以下命令,让它去计算槽 10087 包含的键数量,那么命令将返回 0 作为结果:
127.0.0.1:30001> CLUSTER COUNTKEYSINSLOT 10087 (integer) 0
如果我们与负责处理槽 10087 的节点 30002 进行连接,并执行 CLUSTER COUNTKEYS-INSLOT 命令,那么命令将正确地返回槽 10087 包含的键数量:
127.0.0.1:30002> CLUSTER COUNTKEYSINSLOT 10087 (integer) 42
-
其他信息
-
复杂度:O(log(N)),其中 N 为执行命令的节点包含的键数量。
-
版本要求:CLUSTER COUNTKEYSINSLOT 命令从 Redis 3.0.0 版本开始可用。
-
CLUSTER GETKEYSINSLOT:获取槽包含的键
用户可以通过执行以下命令,获取指定槽包含的键:
CLUSTER GETKEYSINSLOT slot count
命令的 slot 参数用于指定槽,而 count 参数则用于指定命令允许返回的最大键数量。
举个例子,如果我们想要从槽 523 中获取最多 10 个键,那么可以执行以下命令:
127.0.0.1:30001> CLUSTER GETKEYSINSLOT 523 10
1) "article::1750"
2) "article::4022"
因为槽 523 只包含了 "article::1750" 和 "article::4022" 这两个键,所以命令只返回了这两个键。
-
只获取当前节点包含的键
与 CLUSTER COUNTKEYSINSLOT 命令一样,CLUSTER GETKEYSINSLOT 命令在尝试获取槽包含的键时也只会在执行该命令的节点中进行查找:如果执行命令的节点并不是负责处理给定槽的节点,那么命令将无法找到任何可以返回的键。因此,为了正确地获取槽包含的键,用户必须向正确的节点发送 CLUSTER GETKEYSINSLOT 命令。
-
其他信息
-
复杂度:O(log(N)+M),其中 N 为执行命令的节点包含的键数量,而 M 则为命令返回的键数量。
-
版本要求:CLUSTER GETKEYSINSLOT 命令从 Redis 3.0.0 版本开始可用。
-
CLUSTER SETSLOT:改变槽的状态
CLUSTER SETSLOT 命令拥有 4 个子命令,它们可以改变给定槽在节点中的状态,从而实现节点之间的槽迁移以及集群重分片:
CLUSTER SETSLOT slot IMPORTING source-node-id
CLUSTER SETSLOT slot MIGRATING destination-node-id
CLUSTER SETSLOT slot NODE node-id
CLUSTER SETSLOT slot STABLE
接下来将分别介绍这 4 个子命令。
-
导入槽
通过在节点上执行 IMPORTING 子命令,用户可以让节点的指定槽进入 “导入中” (importing)状态,处于该状态的槽允许从源节点中导入槽数据:
CLUSTER SETSLOT slot IMPORTING source-node-id
该命令在成功执行之后将返回 OK 作为结果。
举个例子,如果我们想要让节点 30002 的槽 5460 进入 “导入中” 状态,并允许它从 ID 为 3f2b7eea74079afe6b57ce1d2627228990582d04 的节点 30001 中导入槽数据,那么可以执行以下命令:
127.0.0.1:30002> CLUSTER SETSLOT 5460 IMPORTING 3f2b7eea74079afe6b57ce1d2627228990582d04 OK
-
迁移槽
通过在节点上执行 MIGRATING 子命令,用户可以让节点的指定槽进入 “迁移中” (migrating)状态,处于该状态的槽允许向目标节点转移槽数据:
CLUSTER SETSLOT slot MIGRATING destination-node-id
举个例子,如果我们想要让节点 30001 的槽 5460 进入 “迁移中” 状态,并允许它向 ID 为 1e8f55652d95a05d21b2afc5243a438b848f5966 的节点 30002 迁移数据,那么可以执行以下命令:
127.0.0.1:30001> CLUSTER SETSLOT 5460 MIGRATING 1e8f55652d95a05d21b2afc5243a438b848f5966 OK
-
将槽指派给节点
在将槽数据从源节点迁移至目标节点之后,用户可以在集群的任一节点执行以下命令,正式将槽指派给目标节点负责:
CLUSTER SETSLOT slot NODE node-id
比如,在将槽 5460 的数据从节点 30001 迁移至节点 30002 之后,我们可以执行以下命令,将槽 5460 正式指派给节点 30002 负责:
-- 1e8f5...f5966为节点30002的ID 127.0.0.1:30002> CLUSTER SETSLOT 5460 NODE 1e8f55652d95a05d21b2afc5243a438b84 855966 OK
集群的其中一个节点在执行了 NODE 子命令之后,对给定槽的新指派信息将被传播至整个集群,目标节点在接收到这一信息之后将移除给定槽的 “导入中” 状态,而源节点在接收到这一信息之后将移除给定槽的 “迁移中” 状态。
-
移除槽的导入/迁移状态
通过执行以下命令,用户可以清除节点指定槽的 “导入中” 或 “迁移中” 状态:
CLUSTER SETSLOT slot STABLE
该命令在成功执行之后将返回 OK 作为结果:
127.0.0.1:30001> CLUSTER SETSLOT 5460 STABLE OK
正如之前所说,因为槽在成功迁移之后会由于 NODE 子命令的作用而自动移除相应节点的 “导入中” 和 “迁移中” 状态,所以在正常情况下,用户并不需要执行 STABLE 子命令。STABLE 子命令的唯一作用,就是在槽迁移出错或者重分片出错时,手动移除相应节点的槽状态。
-
其他信息
-
复杂度:CLUSTER SETSLOT 命令的所有子命令的复杂度都为 O(1)。
-
版本要求:CLUSTER SETSLOT 命令的所有子命令从 Redis 3.0.0 版本开始可用。
-