Redis如何高效刪除大key
大key的刪除問(wèn)題
大key(bigkey)是指 key 的 value 是個(gè)龐然大物,例如 Hashes, Sorted Sets, Lists, Sets,日積月累之后,會(huì)變得非常大,可能幾十上百M(fèi)B,甚至到GB。
如果對(duì)這類大key直接使用 del 命令進(jìn)行刪除,會(huì)導(dǎo)致長(zhǎng)時(shí)間阻塞,甚至崩潰。
因?yàn)?del 命令在刪除集合類型數(shù)據(jù)時(shí),時(shí)間復(fù)雜度為 O(M),M 是集合中元素的個(gè)數(shù)。
Redis 是單線程的,單個(gè)命令執(zhí)行時(shí)間過(guò)長(zhǎng)就會(huì)阻塞其他命令,容易引起雪崩。
解決方案
不可靠方案:
- 空閑時(shí)間刪除,如凌晨3-4點(diǎn)刪除
可靠方案:
- 漸進(jìn)式刪除
- UNLINK (4.0版本以后)
1.漸進(jìn)式刪除
思路:
分批刪除,通過(guò) scan 命令遍歷大key,每次取得少部分元素,對(duì)其刪除,然后再獲取和刪除下一批元素。
示例:
- 刪除大 Hashes
步驟:
(1)key改名,相當(dāng)于邏輯上把這個(gè)key刪除了,任何redis命令都訪問(wèn)不到這個(gè)key了
(2)小步多批次的刪除
偽代碼:
# key改名 newkey = "gc:hashes:" + redis.INCR( "gc:index" ) redis.RENAME("my.hash.key", newkey) # 每次取出100個(gè)元素刪除 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個(gè)成員 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) end
2.UNLINK
Redis 4.0 推出了一個(gè)重要命令 UNLINK,用來(lái)拯救 del 刪大key的困境。
UNLINK 工作思路:
(1)在所有命名空間中把 key 刪掉,立即返回,不阻塞。
(2)后臺(tái)線程執(zhí)行真正的釋放空間的操作。
UNLINK 基本可以替代 del,但個(gè)別場(chǎng)景還是需要 del 的,例如在空間占用積累速度特別快的時(shí)候就不適合使用UNLINK,因?yàn)?UNLINK 不是立即釋放空間。
總結(jié)
使用 del 刪除大key可能會(huì)造成長(zhǎng)時(shí)間阻塞,甚至崩潰。
可以使用漸進(jìn)式刪除,對(duì) Hashes, Sorted Sets, Lists, Sets 分別處理,思路相同,先邏輯刪除,對(duì)key改名,使客戶端無(wú)法使用原key,然后使用批量小步刪除。
4.0版本以后可以使用 UNLINK 命令,后臺(tái)線程釋放空間。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Redis優(yōu)雅地實(shí)現(xiàn)延遲隊(duì)列的方法分享
Redisson是Redis服務(wù)器上的分布式可伸縮Java數(shù)據(jù)結(jié)構(gòu),這篇文中主要為大家介紹了Redisson實(shí)現(xiàn)的優(yōu)雅的延遲隊(duì)列的方法,需要的可以參考一下2023-02-02Redis與數(shù)據(jù)庫(kù)數(shù)據(jù)一致性的原因及解決方案
Redis作為一種高效的鍵值對(duì)存儲(chǔ)系統(tǒng),常用于緩存數(shù)據(jù)庫(kù)減少IO操作,下面這篇文章主要介紹了Redis與數(shù)據(jù)庫(kù)數(shù)據(jù)一致性的原因及解決方案,文中介紹的非常詳細(xì),需要的朋友可以參考下2025-04-04Redis未授權(quán)訪問(wèn)配合SSH key文件利用詳解
這篇文章主要給大家介紹了關(guān)于Redis未授權(quán)訪問(wèn)配合SSH key文件利用的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-09-09Redis做預(yù)定庫(kù)存緩存功能設(shè)計(jì)使用
這篇文章主要為大家介紹了Redis做預(yù)定庫(kù)存緩存功能設(shè)計(jì)使用,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-04-04Redis緩存和數(shù)據(jù)庫(kù)的數(shù)據(jù)一致性的問(wèn)題解決
隨業(yè)務(wù)增長(zhǎng),直接操作數(shù)據(jù)庫(kù)性能下降,引入緩存提高讀性能常見(jiàn),但緩存和數(shù)據(jù)庫(kù)的雙寫(xiě)操作會(huì)引發(fā)數(shù)據(jù)不一致問(wèn)題,本文討論幾種常用同步策略,感興趣的可以了解一下2024-09-09Redis server 主從復(fù)制配置實(shí)現(xiàn)
從復(fù)制是指將一個(gè)Redis服務(wù)器的數(shù)據(jù)復(fù)制到其他Redis服務(wù)器的過(guò)程,本文主要介紹了Redis server 主從復(fù)制配置實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2024-02-02