Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

clusterSendPing当中的疑问 #25

Open
lebron374 opened this issue Jun 22, 2018 · 1 comment
Open

clusterSendPing当中的疑问 #25

lebron374 opened this issue Jun 22, 2018 · 1 comment

Comments

@lebron374
Copy link

这里的while循环当中gossipcount的范围是[0,3),不应该是发送3个节点信息么?
另外,gossip = &(hdr->data.ping.gossip[gossipcount]);这个操作会不会污染后面的内存呢?毕竟gossip的数组大小是1.


// 向指定节点发送一个 PING 或者 PONG 信息
void clusterSendPing(clusterLink link, int type) {
unsigned char buf[sizeof(clusterMsg)];
clusterMsg hdr = (clusterMsg) buf;
int gossipcount = 0, totlen;
/
freshnodes is the number of nodes we can still use to populate the
* gossip section of the ping packet. Basically we start with the nodes
* we have in memory minus two (ourself and the node we are sending the
* message to). Every time we add a node we decrement the counter, so when
* it will drop to <= zero we know there is no more gossip info we can
* send. */
// freshnodes 是用于发送 gossip 信息的计数器
// 每次发送一条信息时,程序将 freshnodes 的值减一
// 当 freshnodes 的数值小于等于 0 时,程序停止发送 gossip 信息
// freshnodes 的数量是节点目前的 nodes 表中的节点数量减去 2
// 这里的 2 指两个节点,一个是 myself 节点(也即是发送信息的这个节点)
// 另一个是接受 gossip 信息的节点
int freshnodes = dictSize(server.cluster->nodes)-2;

// 如果发送的信息是 PING ,那么更新最后一次发送 PING 命令的时间戳
if (link->node && type == CLUSTERMSG_TYPE_PING)
    link->node->ping_sent = mstime();

// 设置信息
clusterBuildMessageHdr(hdr,type);
    
/* Populate the gossip fields */
// 每个节点有 freshnodes 次发送 gossip 信息的机会
// 每次向目标节点发送 2 个被选中节点的 gossip 信息(gossipcount 计数)
while(freshnodes > 0 && gossipcount < 3) {

    // 从 nodes 字典中随机选出一个节点(被选中节点)
    struct dictEntry *de = dictGetRandomKey(server.cluster->nodes);
    clusterNode *this = dictGetVal(de);

    clusterMsgDataGossip *gossip;
    int j;

    /* In the gossip section don't include:
     * 以下节点不能作为被选中节点:
     * 1) Myself.
     *    节点本身。
     * 2) Nodes in HANDSHAKE state.
     *    处于 HANDSHAKE 状态的节点。
     * 3) Nodes with the NOADDR flag set.
     *    带有 NOADDR 标识的节点
     * 4) Disconnected nodes if they don't have configured slots.
     *    因为不处理任何槽而被断开连接的节点 
     */
    if (this == server.cluster->myself ||
        this->flags & (REDIS_NODE_HANDSHAKE|REDIS_NODE_NOADDR) ||
        (this->link == NULL && this->numslots == 0))
    {
            freshnodes--; /* otherwise we may loop forever. */
            continue;
    }

    /* Check if we already added this node */
    // 检查被选中节点是否已经在 hdr->data.ping.gossip 数组里面
    // 如果是的话说明这个节点之前已经被选中了
    // 不要再选中它(否则就会出现重复)
    for (j = 0; j < gossipcount; j++) {
        if (memcmp(hdr->data.ping.gossip[j].nodename,this->name,
                REDIS_CLUSTER_NAMELEN) == 0) break;
    }
    if (j != gossipcount) continue;

    /* Add it */

    // 这个被选中节点有效,计数器减一
    freshnodes--;

    // 指向 gossip 信息结构
    gossip = &(hdr->data.ping.gossip[gossipcount]);

    // 将被选中节点的名字记录到 gossip 信息
    memcpy(gossip->nodename,this->name,REDIS_CLUSTER_NAMELEN);
    // 将被选中节点的 PING 命令发送时间戳记录到 gossip 信息
    gossip->ping_sent = htonl(this->ping_sent);
    // 将被选中节点的 PING 命令回复的时间戳记录到 gossip 信息
    gossip->pong_received = htonl(this->pong_received);
    // 将被选中节点的 IP 记录到 gossip 信息
    memcpy(gossip->ip,this->ip,sizeof(this->ip));
    // 将被选中节点的端口号记录到 gossip 信息
    gossip->port = htons(this->port);
    // 将被选中节点的标识值记录到 gossip 信息
    gossip->flags = htons(this->flags);

    // 这个被选中节点有效,计数器增一
    gossipcount++;
}

// 计算信息长度
totlen = sizeof(clusterMsg)-sizeof(union clusterMsgData);
totlen += (sizeof(clusterMsgDataGossip)*gossipcount);
// 将被选中节点的数量(gossip 信息中包含了多少个节点的信息)
// 记录在 count 属性里面
hdr->count = htons(gossipcount);
// 将信息的长度记录到信息里面
hdr->totlen = htonl(totlen);

// 发送信息
clusterSendMessage(link,buf,totlen);

}

@wolfleong
Copy link

我也有这个疑问, 找到答案了吗

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants