Question

I would like to know the internal implementation of Redis Key * . I am implementing a distributed cache functionality.

Was it helpful?

Solution

The internal behavior of the "KEYS *" command is to linearly scan the main dictionary to collect all the keys, and build the result. Expired keys are excluded. Here is the implementation:

void keysCommand(redisClient *c) {
    dictIterator *di;
    dictEntry *de;
    sds pattern = c->argv[1]->ptr;
    int plen = sdslen(pattern), allkeys;
    unsigned long numkeys = 0;
    void *replylen = addDeferredMultiBulkLength(c);

    di = dictGetSafeIterator(c->db->dict);
    allkeys = (pattern[0] == '*' && pattern[1] == '\0');
    while((de = dictNext(di)) != NULL) {
        sds key = dictGetKey(de);
        robj *keyobj;

        if (allkeys || stringmatchlen(pattern,plen,key,sdslen(key),0)) {
            keyobj = createStringObject(key,sdslen(key));
            if (expireIfNeeded(c->db,keyobj) == 0) {
                addReplyBulk(c,keyobj);
                numkeys++;
            }
            decrRefCount(keyobj);
        }
    }
    dictReleaseIterator(di);
    setDeferredMultiBulkLength(c,replylen,numkeys);
}

While this operation occurs, no other command can be executed on the Redis server, the event loop being pending on the result of the KEYS command. If the number of keys is high (> 10K), the clients will notice the server is not anymore responsive.

This is a command intended for debugging purpose only. Do not use it in applications.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top