In my side, I found an issue, which is hard to reproduce but it could crash the redis application once happen. When redis is very busy and lazyfree-lazy-server-del is set to yes, if one client just run the restoreCommand with replace option, then our codes will run as below:

    int deleted = 0;
    **if (replace)
        deleted = dbDelete(c->db,key);**

    if (ttl && !absttl) ttl+=commandTimeSnapshot();
    if (ttl && checkAlreadyExpired(ttl)) {
        if (deleted) {
            rewriteClientCommandVector(c,2,shared.del,key);
            signalModifiedKey(c,c->db,key);
            notifyKeyspaceEvent(NOTIFY_GENERIC,"del",key,c->db->id);
            server.dirty++;
        }
        decrRefCount(obj);
        addReply(c, shared.ok);
        return;
    }

    /* Create the key and set the TTL if any */
    **dbAdd(c->db,key,obj);**

In the dbDelete function, we can indicate the key will be deleted later, but if in this case, a same name key want to insert, then dbAdd() function will crash as below due to the serverAssertWithInfo()

void dbAdd(redisDb *db, robj *key, robj *val) {
    sds copy = sdsdup(key->ptr);
    dictEntry *de = dictAddRaw(db->dict, copy, NULL);
    **serverAssertWithInfo(NULL, key, de != NULL);**
    dictSetVal(db->dict, de, val);
    signalKeyAsReady(db, key, val->type);
    if (server.cluster_enabled) slotToKeyAddEntry(de, db);
    notifyKeyspaceEvent(NOTIFY_NEW,"new",key,db->id);
}

I am not sure why initially, if this case happen, then serverAssertWithInfo will fail. Do we have any idea to avoid the redis crash? If yes, I could try to implement the idea, thanks

Comment From: oranagra

i don't see the problem. dbDelete will completely remove the object from the keyspace (old object just remains in the lazy free queue), so even if the lazy free thread is slow, dbAdd will no longer see the object in the dict and the assert will not happen.

just in case i was missing something, i tried to reproduce this, completely disabled the lazy free bio thread, created a big key, set lazyfree-lazy-server-del to yes, and then used RESTORE REPLACE to override that key. everything seemed to work correctly.

maybe you stumbled into some other bug and wrongly concluded that the problem is what you described?

Comment From: hwware

Thanks Oran, I will try to reproduce this problem if I have chance. And I will let you know any update. Now I will close this issue and reopen it if necessary.