Gossip 协议介绍和Redis集群过大问题

Simply put

The Gossip protocol is a distributed communication protocol used to disseminate information across a network of nodes in a decentralized and fault-tolerant manner. It is commonly used in distributed systems such as peer-to-peer networks, cluster management systems, and in-memory databases.

The Gossip protocol works by having each node periodically exchange information with a random subset of other nodes in the network. Each node maintains a local view of the network state, which is gradually updated as it receives and processes information from other nodes. Nodes may also proactively disseminate information to other nodes if they detect a change in the local state.

The Gossip protocol has several desirable properties, including scalability, fault-tolerance, and eventual consistency. Because each node only communicates with a small subset of other nodes, the protocol can scale to large networks without overwhelming any individual node. Additionally, because the protocol is decentralized, it can tolerate failures or partitions of individual nodes without affecting the overall network.

One of the main challenges of the Gossip protocol is ensuring that information is disseminated efficiently and accurately across the network. To address this challenge, various optimizations and extensions to the basic protocol have been proposed, such as using anti-entropy mechanisms, probabilistic message dissemination, and intelligent message routing algorithms.

redis集群节点过大会发生Gossip 协议广播压力过大

Yes, that is correct. In Redis Cluster, the Gossip protocol is used to communicate cluster state information between nodes. As the number of nodes in the cluster grows, the amount of Gossip communication required to maintain cluster state can become a bottleneck and lead to increased network traffic and latency.
To address this issue, Redis Cluster provides several mechanisms to optimize Gossip communication, including:

  1. Cluster Node Hashing: Redis Cluster uses consistent hashing to distribute keys across the cluster. By partitioning the keyspace into smaller subsets, the amount of Gossip communication required to maintain cluster state can be reduced.
  2. Node Sampling: Rather than communicating with all nodes in the cluster, Redis Cluster uses a sampling technique to select a subset of nodes for Gossip communication. This reduces the overall communication overhead while still maintaining cluster state consistency.
  3. Adaptive Gossip: Redis Cluster uses an adaptive Gossip mechanism that adjusts the frequency and scope of Gossip communication based on the current state of the cluster. This helps to reduce unnecessary communication and improve overall cluster performance.
    Despite these optimizations, Redis Cluster can still experience Gossip-related performance issues when the number of nodes in the cluster is very large. In such cases, it may be necessary to consider alternative cluster architectures or partitioning strategies to better manage network traffic and latency.

代码实例

First, Redis Cluster maintains a data structure called clusterNode to represent each node in the cluster. The clusterNode structure includes information such as the node ID, IP address, port number, and other metadata.

When a new node joins the cluster, it sends a MEET command to one or more existing nodes to announce its presence. Each receiving node then adds the new node to its own clusterNode table and sends a PING command to the new node to confirm its existence.

Every node in the cluster regularly sends PING commands to a random subset of other nodes in the cluster to check their health and update their own clusterNode table. If a node fails to respond to several PING commands, it is marked as failed and removed from the clusterNode table.

Nodes also exchange information about their clusterNode tables using the GOSSIP command. A node randomly selects one or more nodes to gossip with and sends them a message containing its own clusterNode table. The receiving nodes merge the received clusterNode table with their own and propagate the updated table to other nodes in the cluster.

Here is an example of how a PING command is sent to a random node:

void clusterSendPing(void *arg) {
    clusterNode *node = arg;
    redisAssert(node->flags & (REDIS_NODE_MYSELF|REDIS_NODE_HANDSHAKE));
    if (node->flags & REDIS_NODE_MYSELF) {
        redisLog(REDIS_DEBUG,"Skipping self PING %s:%d myself:%d",
            node->ip, node->port, node->flags & REDIS_NODE_MYSELF);
        return;
    }
    redisLog(REDIS_DEBUG,"Sending PING to node %s:%d",
        node->ip, node->port);
    clusterSendMessage(node, CLUSTERMSG_TYPE_PING, NULL, 0);
}

And here is an example of how a GOSSIP command is sent to a random subset of nodes:

void clusterSendGossip(void *arg) {
    clusterNode *node = arg;
    int j, max, count = 0, sent = 0;
    clusterMsg buf[1];
    unsigned char gossip_sent_table[CLUSTER_SLOTS/8+1];

    /* Don't attempt gossip if too many cluster messages are queued in
     * the output buffers. */
    if (listLength(server.cluster->msg_queue) > CLUSTERMSG_MAXLEN*2) return;

    /* Populate our gossip message with random entries selected from our
     * own state table. */
    memset(gossip_sent_table,0,sizeof(gossip_sent_table));
    buf->type = htons(CLUSTERMSG_TYPE_GOSSIP);
    buf->count = htons(clusterCountNonFailingNodes());
    if (nodeIsSlave(node)) {
        clusterNode *master = node->slaveof;
        redisAssert(master != NULL);
        clusterMsgDataGossip(buf) = master->name;
        clusterMsgDataGossipLen(buf) = REDIS_CLUSTER_NAMELEN;
    } else {
        clusterMsgDataGossip(buf) = server.cluster->myself->name;
        clusterMsgDataGossipLen(buf) = REDIS_CLUSTER_NAMELEN;
    }
    if (node->flags & REDIS_NODE_PROTECTED) buf->flags |= htons(CLUSTERMSG_FLAG0_PROTECTED);

    if (server.cluster->myself->numslots > 0)
        clusterMsgDataGossipSlot(buf) = htons(server.cluster->myself->slots[0]);
    else
        clusterMsgDataGossipSlot(buf) = htons(0);

    max = ceil(server.cluster->size / 10.0);
    if (max < 1) max = 1;
    for (j = 0; j < server.cluster->size && sent < max; j++) {
        clusterNode *this = server.cluster->nodes+j;

        if (this == node || clusterNodeIsFailing(this)) continue;
        if (this->flags & (REDIS_NODE_MYSELF|REDIS_NODE_HANDSHAKE)) continue;
        if (gossip_sent_table[this->slots[0]/8] & (1<<(this->slots[0]&7))) continue;

        if (++count > 3) break; /* We need to gossip with at least three nodes. */
        gossip_sent_table[this->slots[0]/8] |= 1<<(this->slots[0]&7);
        memcpy(buf->targets[sent].name,this->name,REDIS_CLUSTER_NAMELEN);
        sent++;
    }
    buf->size = htons(sizeof(clusterMsg)-sizeof(union clusterMsgData));

    clusterSendMessage(node, CLUSTERMSG_TYPE_GOSSIP,
        buf, sizeof(clusterMsg)-sizeof(union clusterMsgData)+(sent*sizeof(clusterMsgTarget)));
}

These are just snippets of code from the larger Redis source codebase, but they demonstrate how the Gossip protocol is implemented in Redis Cluster.

参考

https://blog.csdn.net/DiDi_Tech/article/details/130896033?spm=1000.2115.3001.5927

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

P("Struggler") ?

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值