Redis中的集群(六)

04-23 1761阅读

集群

ASK错误

在进行重新分片期间,源节点向目标节点迁移一个槽的过程中,可能会出现这样一种情况:属于被迁移槽的一部分键值对保存在源节点里面,而另一部分键值对则保存在目标节点里面。当客户端向源节点发送一个与数据库有关的命令,并且命令要处理的数据库键恰好就属于正在被迁移的槽时:

  • 1.源节点会先在自己的数据库里面查找指定的键,如果找到的话,就直接执行客户端发送的命令
  • 2.相反地,如果源节点没能在自己的数据库里面找到指定的键,那么这个键有可能已经被迁移到了目标节点,源节点没能在自己的数据库里面找到指定的键,那么这个键有可能已经被迁移到了目标节点,源节点将向客户端返回一个ASK错误,指引客户端转向正在导入槽的目标节点,并再次发送之前想要执行的命令

    例子

    • 举个例子。如图展示了源节点判断是否需要向客户端发送ASK错误的整个过程,假设节点7002正在向节点7003迁移槽16198,这个槽包含"is"和"love"两个键,其中键"is"还留在节点7002,而键"love"已经被迁移到了节点7003,如果我们向节点7002发送关于键"is"的命令,那么这个命令会直接被节点7002执行:
      127.0.0.1:7002>GET "is"
      "you get the key 'is'"
      

      而如果我们向节点7002发送关于键"love"的命令,那么客户端会先被转向至节点7003,然后再次执行命令:

      127.0.0.1:7002> GET "love"
      -> Redirected to slot [16198] located at 127.0.0.1:7003
      "you get the key 'love'"
      127.0.0.1:7003>
      
      • 被隐藏的ASK错误

        和接到MOVED错误时的情况类似,集群模式的redis-cli在接到ASK错误时也不会打印错误,而是自动根据错误提供的IP地址和端口进行转向动作。如果想看到节点发送的ASK错误的话,可以使用单机模式的redis-cli客户端

        redis-cli -p 7002
        127.0.0.1:7002> GET "love"
        (error) ASK 16198 127.0.0.1:7003
        

        CLUSTER SETSLOT IMPORTING命令的实现

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

        typedef struct clusterState {
        // ...
        clusterNode *importing_slots_from[16384];
        // ...
        } clusterState;
        

        如果importing_slots_from[i]的值不为NULL,而是指向一个clusterNode结构,那么表示当前节点正在从clusterNode所代表的节点导入槽[i].在对集群进行重新分片的时候,向目标节点发送命令

        CLUSTER SETSLOT  IMPORTING 
        

        可以将目标节点clusterState.importing_slots_from[i]的值设置为source_id所代表节点的clusterNode结构。

        例子

        • 举个例子。如果客户端向节点7003发送以下命令:
          # b4348045d1eadca5abd96b8d0d13b0309ed117e1 是节点7002的id
          127.0.0.1:7003> CLUSTER SETSLOT 16198 IMPORTING  b4348045d1eadca5abd96b8d0d13b0309ed117e1
          OK
          

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

          Redis中的集群(六)

          CLUSTER SETSLOT MIGRATING命令的实现

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

          typedef struct clusterState {
          // ...
          clusterNode *migrating_slots_to[16384]
          // ...
          } clusterState;
          

          如果migrating_slots_to[i]的值不为NULL,而是指向一个clusterNode结构,那么表示当前节点正在将槽[i]迁移至clusterNode所代表的节点。

          在对集群进行重新分片的时候,向源节点发送命令:

          CLUSTER SETSLOT  MIGRATING 
          

          可以将源节点clusterState.migrating_slots_to[i]的值设置为target_id所代表节点的clusterNode结构。

          例子

          • 举个例子。如果客户端向节点7002发送以下命令:
            # b4348045d1eadca5abd96b8d0d13b0309ed117e1 是节点7003的ID
            127.0.0.1:7002>CLUSTER SETSLOT 16198 MIGRATING  b4348045d1eadca5abd96b8d0d13b0309ed117e1
            

            那么节点7002的clusterstate.migrating_slots_to数组将变成如图所示的样子

            Redis中的集群(六)

            ASK错误

            如果节点收到一个关于键key的命令请求,并且键key所属的槽i正好就指派给了这个节点,那么节点会尝试在自己的数据库里查找键key,如果找到了的话,节点就直接执行客户端发送的命令。与此相反,如果节点没有在自己的数据库里找到键key,那么系欸但会检查自己的clusterState.migrating_slots_to[i],

            看键key所属的槽i是否正在进行迁移,如果槽i的确在进行迁移的话,那么节点会向客户端发送一个ASK错误,引导客户端正在导入槽i的节点去查找键key。

            例子

            • 举个例子。假设在节点7002向节点7003迁移槽16198期间,有一个客户端向节点发送命令:
              GET "love"
              

              因为键"love"正好属于槽16198,所以节点7002会首先在自己的数据库中查找键"love",但并没有找到,通过检查自己的clusterState.migrating_slots_to[16198],节点7002发现自己正在将槽16198迁移至节点7003,于是它向客户端返回错误:

              ASK 16198 127.0.0.1:7003
              

              这个错误表示客户端可以尝试到IP为127.0.0.1,端口号为7003的节点去执行和槽16198有关的操作,如图所示.接到ASK错误的客户端会根据错误提供的IP地址和端口号,转向至正在导入槽的目标节点,然后首先向目标节点发送一个ASKING命令,之后再重新发送原本想要执行的命令。

              当客户端接收到节点7002返回的以下错误时:

              ASK 16198 127.0.0.1:7003
              

              客户端会转向至节点7003,首先发送命令:

              ASKING
              

              然后再次发送命令:

              GET "love"
              

              并获得回复:

              "you get the key 'love'"
              

              Redis中的集群(六)

              Redis中的集群(六)

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]