skip to Main Content

Document says that "O(N) where N is the number of clients already subscribed to a channel"

Does N means the number of clients who subscribing the channel which I want to unsubscribe, or who subscribing any channel?

2

Answers


  1. It means the sum of all clients subscribed to all the channels you unsubscribe in the batch operation.

    UNSUBSCRIBE [channel [channel ...]]

    Login or Signup to reply.
  2. Good question, like @JeanJacquesGourdin said, it is sum of clients of all channels that you are going to unsubscribe. I look into source code of redis 5.0.5, here is what I found, please correct me if I am wrong, thanks in advance

    1. There is a server side hashtable called server.pubsub_channels, it keeps track of all channels and its subscribed clients
    2. when you want to unsubscribe one channel, the server will try to remove your client from list of the server.pubsub_channels[your_channel], and it is a O(N) time complexity operation to iter through this list. 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;
    }
    
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search