Redis如何高效刪除大key
大key的刪除問題
大key(bigkey)是指 key 的 value 是個龐然大物,例如 Hashes, Sorted Sets, Lists, Sets,日積月累之后,會變得非常大,可能幾十上百MB,甚至到GB。
如果對這類大key直接使用 del 命令進(jìn)行刪除,會導(dǎo)致長時間阻塞,甚至崩潰。
因為 del 命令在刪除集合類型數(shù)據(jù)時,時間復(fù)雜度為 O(M),M 是集合中元素的個數(shù)。
Redis 是單線程的,單個命令執(zhí)行時間過長就會阻塞其他命令,容易引起雪崩。
解決方案
不可靠方案:
- 空閑時間刪除,如凌晨3-4點刪除
可靠方案:
- 漸進(jìn)式刪除
- UNLINK (4.0版本以后)
1.漸進(jìn)式刪除
思路:
分批刪除,通過 scan 命令遍歷大key,每次取得少部分元素,對其刪除,然后再獲取和刪除下一批元素。
示例:
- 刪除大 Hashes
步驟:
(1)key改名,相當(dāng)于邏輯上把這個key刪除了,任何redis命令都訪問不到這個key了
(2)小步多批次的刪除
偽代碼:
# key改名
newkey = "gc:hashes:" + redis.INCR( "gc:index" )
redis.RENAME("my.hash.key", newkey)
# 每次取出100個元素刪除
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
end- 刪除大 Lists
偽代碼:
# key改名
newkey = "gc:hashes:" + redis.INCR("gc:index")
redis.RENAME("my.list.key", newkey)
# 刪除
while redis.LLEN(newkey) > 0
redis.LTRIM(newkey, 0, -99)
end- 刪除大 Sets
偽代碼:
# key改名
newkey = "gc:hashes:" + redis.INCR("gc:index")
redis.RENAME("my.set.key", newkey)
# 每次刪除100個成員
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
end- 刪除大 Sorted Sets
偽代碼:
# key改名
newkey = "gc:hashes:" + redis.INCR("gc:index")
redis.RENAME("my.zset.key", newkey)
# 刪除
while redis.ZCARD(newkey) > 0
redis.ZREMRANGEBYRANK(newkey, 0, 99)
end2.UNLINK
Redis 4.0 推出了一個重要命令 UNLINK,用來拯救 del 刪大key的困境。
UNLINK 工作思路:
(1)在所有命名空間中把 key 刪掉,立即返回,不阻塞。
(2)后臺線程執(zhí)行真正的釋放空間的操作。
UNLINK 基本可以替代 del,但個別場景還是需要 del 的,例如在空間占用積累速度特別快的時候就不適合使用UNLINK,因為 UNLINK 不是立即釋放空間。
總結(jié)
使用 del 刪除大key可能會造成長時間阻塞,甚至崩潰。
可以使用漸進(jìn)式刪除,對 Hashes, Sorted Sets, Lists, Sets 分別處理,思路相同,先邏輯刪除,對key改名,使客戶端無法使用原key,然后使用批量小步刪除。
4.0版本以后可以使用 UNLINK 命令,后臺線程釋放空間。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
深度剖析Redis字符串操作指南從入門到實戰(zhàn)應(yīng)用
Redis字符串類型二進(jìn)制安全,支持文本、數(shù)字、二進(jìn)制等數(shù)據(jù),涵蓋基礎(chǔ)操作、數(shù)字計算、過期管理及分布式鎖等應(yīng)用,結(jié)合優(yōu)化策略提升系統(tǒng)性能,本文給大家介紹Redis字符串操作指南,感興趣的朋友一起看看吧2025-07-07
Redis底層數(shù)據(jù)結(jié)構(gòu)SkipList的實現(xiàn)
本文主要介紹了Redis底層數(shù)據(jù)結(jié)構(gòu)SkipList的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05
Redis Sorted Set 跳表的實現(xiàn)示例
本文詳細(xì)解析了Redis中SortedSet跳表的實現(xiàn)原理,闡述了跳表的基本概念、結(jié)構(gòu)及其在SortedSet中的應(yīng)用,同時也指出了跳表在實際使用中的優(yōu)勢和局限,可以更好地運用Redis的SortedSet,優(yōu)化高并發(fā)環(huán)境中的數(shù)據(jù)查詢與操作,感興趣的可以了解一下2024-10-10

