关于被导入的数组,是会被记录在目标节点的importing_slots_form数组中的,这个数组是一个clusterNode数组,是用来记录当前节点正在从哪些节点导入槽
typedef struct clusterState(
//…
clusterNode *importing_slots_from[16384];
//…
)clusterState;
可以看到这是一个clusterNode数组,但容量却是16384,对应的是槽的数量,使用索引i记录槽
举个栗子
假如importing_slots_from[i]指向的不是空,而是一个具体的clusterNode结构,那么就代表当前节点正在从这个clusterNode对应的节点导入槽i。
在对集群进行重新分片的时候,第一个命令是
cluster setslot importing
i代表的是16384个槽中的哪个槽,source_id是代表节点在集群里面的runid
这条命令的作用其实就是,当目标节点接收到这条命令,会修改importing_slots_from数组,在索引为i的位置上,放入source_id对应的clusterNode结构。
[](()cluster setslot migrating命令的实现cluster setslot migrating命令是对于第二个步骤,就是redis-trib向源节点发送该命令,让源节点准备发送槽的count个键值对。
在clusterState结构里面是使用一个migrating_slots_to数组来记录了当前节点正在迁移至其他节点的槽,也是一个clusterNode数组
typedef struct clusterState(
//…
clusterNode *migrating_slots_to[16384];
//…
)clusterState;
这个与importing_slots_from一样,也是使用索引代表槽,然后对应数组的位置有没有节点,去代表该槽是否正在被发送中,发送给里面对应的clusterNode
在对集群进行重新分片的时候,会向源节点发送命令
cluster setslots migrating
i就代表槽的位置,target_id对应目标节点在集群中的runid。
当源节点收到该命令的时候,就会在migrating_slots_to[i]里保存target_id对应的custerNode节点
总体还是跟importing_slots_to很类似的
[](()ASK错误前面提到过,如果节点收到一个关于键Key的命令请求,会先去计算这个键属于的是哪个槽,然后看这个槽是不是被委派给当前节点,如果是,就自己进行执行,如果不是就发送MOVED指令,指引客户端去找正确的节点。
假设,现在槽是委派给当前节点的,那么当前节点就回去数据库(集群节点的数据库只会使用0号数据库)里找,找的时候会先检查自己的clusterState.migrating_slots_to[i](i是指定的槽)是否为空,如果为空就代表该槽 《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 没有进行转移,去数据库里面找,如果不为空,那么发送一个ASK错误,指引客户端到导入槽i的节点去查找键key。
接收到ASK错误的客户端会根据错误提供的IP地址和端口号,转向至正在导入槽的目标节点,然后首先向目标节点发送一个ASKING命令,之后再重新发送自己想要执行的命令
[](()ASKING命令ASKING命令唯一要做的就是打开发送该命令的客户端的REDIS_ASKING标识
def ASKING():
#打开REDIS_ASKING标识
client.flags |= REDIS_ASKING
#向客户端返回OK回复
reply(“ok”)



