Redis取消订阅时间复杂性

ttp71kqs  于 2022-09-21  发布在  Redis
关注(0)|答案(2)|浏览(175)

文档中写道:“O(N),其中N是已经订阅某一频道的客户的数量”

N是指订阅我想要取消订阅的频道的客户数量,还是指订阅任何频道的客户数量?

enyaitl3

enyaitl31#

它意味着在批处理操作中订阅了您取消订阅的所有频道的所有客户端的总和。

UNSUBSCRIBE [channel [channel ...]]

nfg76nw0

nfg76nw02#

问得好,就像@JeanJacquesGourdin说的那样,你要取消订阅的是所有频道的客户总和。我研究了Redis 5.0.5的源代码,这是我发现的,如果我错了,请纠正我,提前谢谢

1.有一个名为server.pubSub_Channel的服务器端哈希表,它跟踪所有频道及其订阅的客户端
1.当您想要取消订阅一个频道时,服务器会尝试将您的客户端从服务器.pubSub_Channel[Your_Channel]的列表中移除,通过该列表对ITER进行O(N)时间复杂度的操作。ln = listSearchKey(clients,c);

int pubsubUnsubscribeChannel(client *c, robj *channel, int notify) {
    dictEntry *de;
    list *clients;
    listNode *ln;
    int retval = 0;

    /* Remove the channel from the client -> channels hash table */
    incrRefCount(channel); /* channel may be just a pointer to the same object
                            we have in the hash tables. Protect it... */
    if (dictDelete(c->pubsub_channels,channel) == DICT_OK) {
        retval = 1;
        /* Remove the client from the channel -> clients list hash table */
        de = dictFind(server.pubsub_channels,channel);
        serverAssertWithInfo(c,NULL,de != NULL);
        clients = dictGetVal(de);
        ln = listSearchKey(clients,c); /**the iteration occurs here**/
        serverAssertWithInfo(c,NULL,ln != NULL);
        listDelNode(clients,ln);
        if (listLength(clients) == 0) {
            /* Free the list and associated hash entry at all if this was
             * the latest client, so that it will be possible to abuse
             * Redis PUBSUB creating millions of channels. */
            dictDelete(server.pubsub_channels,channel);
        }
    }
    /* Notify the client */
    if (notify) {
        addReply(c,shared.mbulkhdr[3]);
       ...
    }
    decrRefCount(channel); /* it is finally safe to release it */
    return retval;
}

listNode *listSearchKey(list *list, void *key)
{
    listIter iter;
    listNode *node;

    listRewind(list, &iter);
    while((node = listNext(&iter)) != NULL) {
        if (list->match) {
            if (list->match(node->value, key)) {
                return node;
            }
        } else {
            if (key == node->value) {
                return node;
            }
        }
    }
    return NULL;
}

相关问题