redis源码阅读之cluster(二) 管理命令及实现

cluster 管理命令及实现

cluster管理

cluster reset

cluster reset [hard|soft]

cluster reset 分为soft reset和hard reset,不指定的情况下为soft
执行reset后:

  1. 所有节点会被forget
  2. 所有已指派过的slot会被释放清空
  3. node会变更为master
  4. nodes.conf 文件会被更新并且cluster state被修改
  5. 如果node是slave,数据会被flush
  6. (hard) 生成新的nodeid
  7. (hard) epoch 被重置为0

cluster bumpepoch

cluster bumpepoch 

这是一个redis的隐藏命令。bumpepoch检查执行命令的节点当前的epoch,并与集群的最大epoch比较,如果当前
节点的epoch为0,或者小于集群的maxEpoch,则将集群的epoch加1,并且节点的configEpoch设置为等于currentEpoch。

cluster info

cluster info

获取当前节点的集群信息,
包括集群状态 slot分配状态 epoch。

node管理

cluster meet

cluster meet ip port

cluster meet 进行节点间的握手,握手成功后,新节点加入到集群。

if (!strcasecmp(c->argv[1]->ptr, "meet") && c->argc == 4)
{
    // 校验ip port正确后开始进行握手
    if (clusterStartHandshake(c->argv[2]->ptr, port) == 0 &&errno == EINVAL)
}
int clusterStartHandshake(char *ip, int port)
{
    // ... ip port 合法性校验
    {
         // ip 不合法,返回EINVAL
        errno = EINVAL;
        return 0;
    }
    // 已经处于握手中,返回错误 EAGAIN
    if (clusterHandshakeInProgress(norm_ip, port))
    {
        errno = EAGAIN;
        return 0;
    }
    // 创建cluster node对象
    n = createClusterNode(NULL, CLUSTER_NODE_HANDSHAKE | CLUSTER_NODE_MEET);
    memcpy(n->ip, norm_ip, sizeof(n->ip));
    n->port = port;
    // 将新的node加入到集群。
    // 此时,cluster state的node列表该节点还是处于handshake状态,只有后续心跳同步到其他节点后才会更新节点状态
    clusterAddNode(n);
}

clusterAddNode只是把node加入到cluster->nodes的map中
并且flags被设置为handshake|meet。clusterCron任务会向该新节点发起tcp连接,并通过心跳gossip发送meet状态指令,
发送玩meet后,meet flags会被清空。meet flag被清空后,下一次心跳降发送ping指令,当收到pong响应后,如果该节点还处于
handshake,则handshake flags将被清空,节点成功加入cluster。

cluster nodes

nodes 返回集群所有的节点信息,通过clusterGenNodeDescription生成node 信息的描述
包括 nodeid ip:port slots 信息

slot管理

cluster flushslots

清空该节点所有已分配的slots,删除node的slot信息。

cluster addslots|delslots

cluster addslots [slot] ...
cluster delslots [slot] ... 

添加删除slot只是简单地更新node的slot标记位,唯一需要注意的是,如果添加的slot处于importing状态
因为该node已经拥有了这个slot,因此需要清空这个slot的importing状态。

cluster setslot

SETSLOT 10 MIGRATING 
SETSLOT 10 IMPORTING 
SETSLOT 10 STABLE
SETSLOT 10 NODE 

cluster setslot 用于在集群节点间的dlot迁移。setslot命令只能在master节点上执行。
migrating将当前节点的slot迁移到nodeid,

if (!strcasecmp(c->argv[3]->ptr, "migrating") && c->argc == 5)
{
    // 必须在当前节点执行
    if (server.cluster->slots[slot] != myself)
    {
        addReplyErrorFormat(c, "I'm not the owner of hash slot %u", slot);
        return;
    }
    // nodeid 必须是已知的节点
    if ((n = clusterLookupNode(c->argv[4]->ptr)) == NULL)
    {
        addReplyErrorFormat(c, "I don't know about node %s",
                            (char *)c->argv[4]->ptr);
        return;
    }
    // 添加migrating节点到migrating slots当中
    server.cluster->migrating_slots_to[slot] = n;
}
  • importing将slot从目标节点nodeid导入到当前节点,相应的该slot不应该属于当前节点。
  • stable回滚slot的迁移状态,清除migrating和importing的标识。
  • node将slot指派给nodeid所在节点,完成指派之前,需要判断当前slot是否还有key,如果还有,则无法完成slot的指派。
    如果当前节点的slot之前处于importing状态,则需要更新epoch,以便slot的更新信息更新为最新的version同步到整个集群。

你可能感兴趣的:(redis源码阅读之cluster(二) 管理命令及实现)