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;
}
2条答案
按热度按时间enyaitl31#
它意味着在批处理操作中订阅了您取消订阅的所有频道的所有客户端的总和。
UNSUBSCRIBE [channel [channel ...]]
nfg76nw02#
问得好,就像@JeanJacquesGourdin说的那样,你要取消订阅的是所有频道的客户总和。我研究了Redis 5.0.5的源代码,这是我发现的,如果我错了,请纠正我,提前谢谢
1.有一个名为server.pubSub_Channel的服务器端哈希表,它跟踪所有频道及其订阅的客户端
1.当您想要取消订阅一个频道时,服务器会尝试将您的客户端从服务器.pubSub_Channel[Your_Channel]的列表中移除,通过该列表对ITER进行O(N)时间复杂度的操作。
ln = listSearchKey(clients,c);