一、重新分片的概念

  • Redis集群的重新分片操作可以将任意数量已经指派给某个节点(源节点)的槽改为指派给另一个节点(目标节点),并且相关槽所属的键值对也会从源节点被移动到目标节点
  • 重新分片操作可以在线(online)进行,在重新分片的过程中,集群不需要下线,并且源节点和目标节点都可以继续处理命令请求

二、redis-trib软件

  • Redis集群的重新分片操作是由Redis的集群管理软件redis-trib负责执行的,Redis提供了进行重新分片所需的所有命令,而redis-trib则通过向源节点和目标节点发送命令来进行重新分片操作

redis-trib对集群的单个槽slot进行重新分片的步骤如下

  • ①redis-trib对目标节点发送“CLUSTER SETSLOT IMPORTING <source_id>”命令, 让目标节点准备好从源节点导入(import)属于槽slot的键值对
  • ②redis-trib对源节点发送“CLUSTER SETSLOT MIGRATING <target_id>”命令,让源节点准备好将属于槽slot的键值对迁移(migrate)至目标节点
  • ③redis-trib向源节点发送“CLUSTER GETKEYSINSLOT ”命令,获得最多count个属于槽slot的键值对的键名(key name)
  • ④对于步骤3获得的每个键名,redis-trib都向源节点发送一个“MIGRATE <target_ip> <target_port> <key_name> 0 ”命令,将被选中的键原子地从源节点迁移至目标节点
  • ⑤重复执行步骤3和步骤4,直到源节点保存的所有属于槽slot的键值对都被迁移至目标节点为止。每次迁移键的过程如下图所示
  • ⑥redis-trib向集群中的任意一个节点发送CLUSTER SETSLOTNODE 命令,将槽slot指派给目标节点,这一指派信息会通过消息发送至整个集群,最终集群中的所 有节点都会知道槽slot已经指派给了目标节点

cluster恢复 redis redis cluster 重新分配slot_键值对


如果重新分片涉及多个槽,那么redis-trib将对每个给定的槽分别执行上面给出的步骤下图展示了对槽slot进行重新分片的整个过程

cluster恢复 redis redis cluster 重新分配slot_键值对_02

三、CLUSTER SETSLOT IMPORTING命令的实现

clusterState结构的importing_slots_from数组记录了当前节点正在从其他节点导入的槽:

  • 如果importing_slots_from[i]的值不为NULL,而是指向一个clusterNode结构,那么表示当前节点正在从clusterNode所代表的节点导入槽i
typedef struct clusterState {
    // ...
    clusterNode *importing_slots_from[16384];
    // ...
} clusterState;

在对集群进行重新分片的时候,向目标节点发送命令,可以将目标节点clusterState.importing_slots_from[i]的值设置为source_id所代表节点的clusterNode结构:

CLUSTER SETSLOT <i> IMPORTING <source_id>

演示案例

  • 如果客户端向节点7003发送以下命令:

cluster恢复 redis redis cluster 重新分配slot_cluster恢复 redis_03

  • 那么节点7003的clusterState.importing_slots_from数组将变成下图所示的样子

cluster恢复 redis redis cluster 重新分配slot_数组_04

四、CLUSTER SETSLOT MIGRATING命令的实现

clusterState结构的migrating_slots_to数组记录了当前节点正在迁移至其他节点的槽:

  • 如果migrating_slots_to[i]的值不为NULL,而是指向一个clusterNode结构,那么表示当前
    节点正在将槽i迁移至clusterNode所代表的节点
typedef struct clusterState {
    // ...
    clusterNode *migrating_slots_to[16384];
    // ...
} clusterState;
  • 在对集群进行重新分片的时候,向源节点发送命令,可以将源节点clusterState.migrating_slots_to[i]的值设置为target_id所代表节点的
    clusterNode结构:
CLUSTER SETSLOT <i> MIGRATING <target_id>

演示案例

  • 如果客户端向节点7002发送以下命令:

cluster恢复 redis redis cluster 重新分配slot_redis_05

  • 那么节点7002的clusterState.migrating_slots_to数组将变成下图所示的样子

cluster恢复 redis redis cluster 重新分配slot_cluster恢复 redis_06