How to Safely Delete Large Redis Keys Without Blocking Your Server
This article explains why using DEL on massive Redis keys can cause long‑lasting blocks or crashes, and presents incremental scan‑based deletion and the UNLINK command as reliable, non‑blocking alternatives for Hashes, Lists, Sets, and Sorted Sets.
1. The BigKey Deletion Issue
A bigkey refers to a Redis key whose value is a massive data structure such as Hashes, Sorted Sets, Lists or Sets, which can grow to dozens or hundreds of megabytes, even gigabytes.
Deleting such a bigkey directly with the DEL command may cause long‑time blocking or even crashes because DEL on collection types has a time complexity of O(M), where M is the number of elements.
Since Redis is single‑threaded, a long‑running command blocks all other operations, potentially leading to a cascade failure.
For non‑string bigkeys, do not use DEL ; use HSCAN , SSCAN , ZSCAN for incremental deletion.
2. Solutions
Reliable approaches:
Incremental deletion
UNLINK (available from Redis 4.0)
1. Incremental Deletion
Idea: batch‑delete by scanning the bigkey with a SCAN ‑type command, retrieving a small number of elements each time, deleting them, and then proceeding to the next batch.
Example for deleting large Hashes:
Delete large Hashes
Steps:
(1) Rename the key, which logically removes it so that client commands can no longer access it.
(2) Perform small‑batch deletions.
Pseudo‑code:
# key rename
newkey = "gc:hashes:" + redis.INCR("gc:index")
redis.RENAME("my.hash.key", newkey)
# delete 100 elements per batch
cursor = 0
loop
cursor, hash_keys = redis.HSCAN(newkey, cursor, "COUNT", 100)
if hash_keys count > 0
redis.HDEL(newkey, hash_keys)
end
if cursor == 0
break
end
endExample for deleting large Lists:
Delete large Lists
Pseudo‑code:
# key rename
newkey = "gc:hashes:" + redis.INCR("gc:index")
redis.RENAME("my.list.key", newkey)
# delete
while redis.LLEN(newkey) > 0
redis.LTRIM(newkey, 0, -99)
endExample for deleting large Sets:
Delete large Sets
Pseudo‑code:
# key rename
newkey = "gc:hashes:" + redis.INCR("gc:index")
redis.RENAME("my.set.key", newkey)
# delete 100 members per batch
cursor = 0
loop
cursor, members = redis.SSCAN(newkey, cursor, "COUNT", 100)
if size of members > 0
redis.SREM(newkey, members)
end
if cursor == 0
break
end
endExample for deleting large Sorted Sets:
Delete large Sorted Sets
Pseudo‑code:
# key rename
newkey = "gc:hashes:" + redis.INCR("gc:index")
redis.RENAME("my.zset.key", newkey)
# delete
while redis.ZCARD(newkey) > 0
redis.ZREMRANGEBYRANK(newkey, 0, 99)
end2. UNLINK
Redis 4.0 introduced the UNLINK command to alleviate the problems of using DEL on bigkeys.
UNLINK works by:
Removing the key from all namespaces instantly and returning without blocking.
Freeing the memory in a background thread.
In most cases UNLINK can replace DEL, but there are scenarios where DEL is still needed, such as when space consumption grows extremely fast and immediate memory release is required, because UNLINK does not free memory instantly.
3. Summary
Using DEL to delete bigkeys may cause long blocking or crashes.
Incremental deletion—renaming the key then batch‑deleting elements—works for Hashes, Sorted Sets, Lists, and Sets.
From Redis 4.0 onward, the UNLINK command can be used to delete bigkeys asynchronously, with a background thread handling memory reclamation.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java High-Performance Architecture
Sharing Java development articles and resources, including SSM architecture and the Spring ecosystem (Spring Boot, Spring Cloud, MyBatis, Dubbo, Docker), Zookeeper, Redis, architecture design, microservices, message queues, Git, etc.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
