0
votes

As the docs of RENAME says:

Renames key to newkey. It returns an error when key does not exist. If newkey already exists it is overwritten, when this happens RENAME executes an implicit DEL operation, so if the deleted key contains a very big value it may cause high latency even if RENAME itself is usually a constant-time operation.

As we know, DEL is blocking while UNLINK is non-blocking.

So I have two questions:

  • If the deleted key contains a very big value, it seems that executing an implicit UNLINK would be better. Why redis determines to use DEL?

  • If I manully execute UNLINK then RENAME with transaction, will the high latency be avoided?

1

1 Answers

2
votes

The "implicit DEL operation" is not the same as a DEL command called by a user. You can config it to use async or sync delete. The reason behind it is to probably give the user more control.

In the redis config file, on the part of LAZY FREEING, it says

DEL, UNLINK and ASYNC option of FLUSHALL and FLUSHDB are user-controlled. It's up to the design of the application to understand when it is a good idea to use one or the other. However the Redis server sometimes has to delete keys or flush the whole database as a side effect of other operations.** Specifically Redis deletes objects independently of a user call in the following scenarios:

.... For example the RENAME command may delete the old key content when it is replaced with >another one. ....

In all the above cases the default is to delete objects in a blocking way, like if DEL was called. However you can configure each case specifically in order to instead release memory in a non-blocking way like if UNLINK was called, using the following configuration directives.

Then there's the config

lazyfree-lazy-server-del no

Just switch it to YES then it will behave like UNLINK

I checked the source code,

For Redis version 5.0, this function is called when you call RENAME command

void renameGenericCommand(client *c, int nx) {
// some code....
// When source and dest key is the same, no operation is performed,
// if the key exists, however we still return an error on unexisting key. 
if (sdscmp(c->argv[1]->ptr,c->argv[2]->ptr) == 0) samekey = 1;

// some code ...

if (samekey) {
    addReply(c,nx ? shared.czero : shared.ok);
    return;
}
       ...
    /* Overwrite: delete the old key before creating the new one
     * with the same name. */
    dbDelete(c->db,c->argv[2]);
}

This is the dbDelete function it called

int dbDelete(redisDb *db, robj *key) {
return server.lazyfree_lazy_server_del ? dbAsyncDelete(db,key) :
                                         dbSyncDelete(db,key);

}

As you can see, it does refer to the config of lazyfree-lazy-server-del