Is the UNLINK command always better than DEL command?
Asked Answered
U

2

39

In Redis 4.0, there is a new command UNLINK to delete the keys in Redis memory.

This command is very similar to DEL: it removes the specified keys. Just like DEL a key is ignored if it does not exist. However the command performs the actual memory reclaiming in a different thread, so it is not blocking, while DEL is. This is where the command name comes from: the command just unlinks the keys from the keyspace. The actual removal will happen later asynchronously.

So one can always (100% times) use UNLINK instead of DEL as UNLINK is nonblocking, unlike DEL, right?

Urey answered 22/8, 2017 at 12:59 Comment(0)
F
47

Before discussing which one is better, let's take a look at the difference between these commands. Both DEL and UNLINK free the key part in blocking mode. And the difference is the way they free the value part.

DEL always frees the value part in blocking mode. However, if the value is too large, e.g. too many allocations for a large LIST or HASH, it blocks Redis for a long time. In order to solve the problem, Redis implements the UNLINK command, i.e. an 'non-blocking' delete.

In fact, UNLINK is NOT always non-blocking/async. If the value is small, e.g. the size of LIST or HASH is less than 64, the value will be freed immediately. In this way, UNLINK is almost the same as DEL, except that it costs a few more function calls than DEL. However, if the value is large, Redis puts the value into a list, and the value will be freed by another thread i.e. the non-blocking free. In this way, the main thread has to do some synchronization with the background thread, and that's also a cost.

In a conclusion, if the value is small, DEL is at least, as good as UNLINK. If value is very large, e.g. LIST with thousands or millions of items, UNLINK is much better than DEL. You can always safely replace DEL with UNLINK. However, if you find the thread synchronization becomes a problem (multi-threading is always a headache), you can rollback to DEL.

UPDATE:

Since Redis 6.0, there's a new configuration: lazyfree-lazy-user-del. You can set it to be yes, and Redis will run the DEL command as if running a UNLINK command.

Fender answered 22/8, 2017 at 14:42 Comment(4)
>> if you find the thread synchronization becomes a problem << How would you know when this is a problem?Claireclairobscure
Normally it won't be a problem. However, for each async delete, the background thread needs to get the lock twice, and the foreground (main) thread needs to get the lock once. That might be a problem, e.g. context switch, locking. IMHO, if you find UNLINK is slow (again, normally it's won't), you can replace it with DEL, and do some benchmark.Fender
And for a single key how about I set the expire to 0. Will that be faster?Timorous
@Timorous If you set expire to 0, Redis will delete the key immediately. By default, it deletes the key synchronously, and it will block Redis. However, you can set the lazyfree_lazy_expire config to yes, so that Redis will delete the key asynchronously, which won't block.Fender
B
14

YES. please have a read on Lazy Redis is better Redis from antirez. But the reason is not that the unlink is nonblocking command. The reason is unlink is smarter than del.

UNLINK is a smart command: it calculates the deallocation cost of an object, and if it is very small it will just do what DEL is supposed to do and free the object ASAP. Otherwise the object is sent to the background queue for processing.

Also, I think the more fast way is we do the decision for redis: using DEL for small key, using UNLINK for a huge key such as big list or set. We can decrease the needless calculation of redis.

Bilbrey answered 22/8, 2017 at 14:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.