目錄
- 一、為什么需要淘汰策略? 🤔
- 二、Redis 的淘汰策略詳解 👇
- 三、如何選擇合適的淘汰策略? 🤔???
- 四、如何切換 Redis 的淘汰策略? ??🔧
- 五、總結 🎉
🌟我的其他文章也講解的比較有趣😁,如果喜歡博主的講解方式,可以多多支持一下,感謝🤗!
🌟了解 Redis 大 Key解決方案 請看 : Redis 大 Key:別讓你的 Redis 變成“胖子”!
其他優質專欄: 【🎇SpringBoot】【🎉多線程】【🎨Redis】【?設計模式專欄(已完結)】…等
如果喜歡作者的講解方式,可以點贊收藏加關注,你的支持就是我的動力
?更多文章請看個人主頁: 碼熔burning
一、為什么需要淘汰策略? 🤔
Redis 是一種基于內存的數據庫,速度飛快 🚀,但內存可是寶貴的資源!💰 當 Redis 實例使用的內存達到了你配置的上限 (maxmemory
指令設置的值) 時,就不能再無限制地存新數據了。如果不做處理,后續的寫入操作可能會導致 Redis 內存溢出 (OOM),甚至讓服務掛掉 💥。
為了優雅地處理這種情況,Redis 提供了多種內存淘汰策略。當內存告急 🚨 時,Redis 會根據你選定的策略,自動刪除一些“不那么重要”的鍵(Key),騰出空間來迎接新的數據。
注意: 如果你沒有設置 maxmemory
(或者設為 0),Redis 會嘗試吃掉所有能用的內存,并且不會觸發任何淘汰策略。這種情況下,物理內存耗盡時,操作系統可能會出手干預,把 Redis 進程給“咔嚓”掉。😱
二、Redis 的淘汰策略詳解 👇
Redis 提供了以下幾種主要的淘汰策略 (可以通過 maxmemory-policy
配置項設置):
-
noeviction
(默認策略) 🙅?♀?- 行為: 當內存滿時,任何想寫入更多數據的命令(如
SET
,LPUSH
等,但DEL
和一些只讀命令除外)都會直接報錯 ?。它不會刪除任何現有鍵。 - 含義: 就是不刪!寧可報錯,也絕不丟數據。
- 適用場景:
- 數據極其重要,一絲一毫都不能丟。
- 應用層有完善的錯誤處理和降級機制。
- 主要用作持久化存儲,而不是臨時緩存。
- 行為: 當內存滿時,任何想寫入更多數據的命令(如
-
allkeys-lru
(Least Recently Used - 最近最少使用) ?- 行為: 內存不足時,在所有鍵中,把那個最久沒被訪問(讀或寫)的鍵給請出去。
- 含義: 優先保留“熱乎”的數據,認為剛用過的以后還會用。
- 適用場景:
- 最常見、最通用的策略之一,適合絕大多數緩存場景 👍。
- 你的應用訪問模式符合“熱點數據”原則(剛訪問的,可能馬上又會被訪問)。
- 不知道選啥好的時候,選它一般沒錯。
-
volatile-lru
?- 行為: 內存不足時,只在那些設置了過期時間 (TTL) 的鍵里,找那個最久沒被訪問的鍵淘汰掉。
- 含義: 只在“臨時工”(設置了過期時間的鍵,通常是緩存)里搞淘汰,保護那些“正式工”(沒設過期時間的持久鍵)。
- 適用場景:
- 想明確區分緩存數據和需要長期保存的數據。
- 把 Redis 同時當緩存(設 TTL)和少量持久存儲(不設 TTL)用。
-
allkeys-random
🎲- 行為: 內存不足時,在所有鍵中,閉著眼睛隨機抓一個刪掉。🤷?♂?
- 含義: 完全隨機,不看情面(訪問模式、過期時間)。
- 適用場景:
- 應用的訪問模式極其隨機,或者你壓根不在乎刪了哪個。
- 對淘汰的精確性要求不高,追求極低的淘汰開銷。
- 所有鍵的被訪問概率都差不多。
-
volatile-random
🎰- 行為: 內存不足時,只在設置了過期時間 (TTL) 的鍵里,隨機抓一個刪掉。
- 含義: 只在“臨時工”里隨機淘汰,保護“正式工”。
- 適用場景:
- 和
volatile-lru
類似,想區分緩存和持久數據,但在緩存內部,訪問模式不重要或很隨機,用隨機淘汰省點力氣。
- 和
-
volatile-ttl
?- 行為: 內存不足時,在設置了過期時間 (TTL) 的鍵里,找那個剩余壽命 (Time To Live) 最短 的鍵刪掉。
- 含義: 優先淘汰那些馬上就要“壽終正寢”的鍵,可以認為它們價值最低。
- 適用場景:
- 緩存數據有明確的生命周期,希望先清理快到期的。
- 希望緩存里盡量都是“新鮮出爐”的數據。
-
allkeys-lfu
(Least Frequently Used - 最不經常使用) 🔥 (Redis 4.0+ 新增)- 行為: 內存不足時,在所有鍵中,把那個訪問次數最少的鍵淘汰掉。
- 含義: 優先保留“人氣王”(訪問頻率高的數據),認為訪問次數比最近訪問時間更能體現價值。LFU 會默默記錄每個鍵被訪問了多少次。
- 適用場景:
- 緩存場景中,有些數據可能偶爾才用,但一用就很關鍵(比如配置項);而有些數據可能短時間刷一波訪問量就沒用了。LFU 更擅長保留前者。
- 訪問模式更符合“用得多就是爺”原則。
-
volatile-lfu
👍 (Redis 4.0+ 新增)- 行為: 內存不足時,只在設置了過期時間 (TTL) 的鍵里,找那個訪問次數最少的鍵淘汰掉。
- 含義: 只在“臨時工”里按訪問頻率淘汰,保護“正式工”,并優先保留人氣高的緩存。
- 適用場景:
- 和
allkeys-lfu
類似,但需要保護沒設置過期時間的持久鍵。適合混合存儲,且緩存數據的訪問頻率是決定去留的關鍵。
- 和
💡 重要提示:近似 LRU 和 LFU
為了效率,Redis 實現的 LRU 和 LFU 都不是絕對精確的。它們用了近似算法:Redis 會隨機挑一小撮鍵(默認 5 個,通過 maxmemory-samples
參數配置),然后從這堆里面選出最符合策略(最老、最少用等)的那個來淘汰。樣本量越大,越接近精確,但 CPU 開銷也越大。對大多數應用,默認值就挺好用了!
三、如何選擇合適的淘汰策略? 🤔???
選哪個策略,得看你的應用場景和數據戲份:
-
通用緩存,不確定訪問模式?
- 試試
allkeys-lru
吧!它是老牌明星,通常效果不錯。🌟
- 試試
-
要區分緩存和持久數據?
- 想保護沒設過期時間的“元老”鍵?用
volatile-lru
,volatile-lfu
,volatile-random
, 或volatile-ttl
。 - 在這些
volatile-*
策略里:- 關心誰最近被翻牌子?選
volatile-lru
?。 - 關心誰被翻牌子的次數最多?選
volatile-lfu
🔥 (Redis 4.0+)。 - 想先送走快到期的?選
volatile-ttl
?。 - 隨便刪個臨時的就行?選
volatile-random
🎰。
- 關心誰最近被翻牌子?選
- 想保護沒設過期時間的“元老”鍵?用
-
所有數據都是緩存,訪問頻率比時間更重要?
- 用
allkeys-lfu
🔥 (Redis 4.0+)。
- 用
-
所有數據都是緩存,訪問隨機或不 care 刪哪個?
- 用
allkeys-random
🎲。
- 用
-
數據寶寶一個都不能少,寧可寫入失敗?
- 用
noeviction
🙅?♀? (默認)。記得讓你的應用能處理好寫入錯誤哦!
- 用
四、如何切換 Redis 的淘汰策略? ??🔧
有兩種主要方式來設定或切換策略:
-
通過配置文件 (
redis.conf
) ??📄- 打開你的
redis.conf
文件。 - 找到或加上
maxmemory-policy
這一行。 - 把值改成你想要的策略名,比如:
maxmemory-policy volatile-lru
- 優點: 配置是永久的,Redis 重啟后還在。👍
- 缺點: 改完需要重啟 Redis 服務才能生效。🔄
- 打開你的
-
通過
CONFIG SET
命令 (動態修改) 💻?- 連上 Redis 服務器 (
redis-cli
)。 - 執行
CONFIG SET
命令:
例如,切換到CONFIG SET maxmemory-policy <policy_name>
allkeys-lfu
:CONFIG SET maxmemory-policy allkeys-lfu
- 可以用
CONFIG GET maxmemory-policy
看看當前是啥策略。 - 優點: 立刻生效,不用重啟 Redis,非常靈活!💨
- 缺點: 這只是臨時修改。Redis 一重啟,就又變回
redis.conf
里寫的那樣了。😅 - 讓動態修改“轉正”: 想讓動態修改永久生效?執行
CONFIG SET
之后,再執行CONFIG REWRITE
命令。這會把當前運行的配置寫回redis.conf
文件(前提是 Redis 有權限寫這個文件)。
- 連上 Redis 服務器 (
# 示例:動態設置并永久保存
redis-cli
127.0.0.1:6379> CONFIG SET maxmemory-policy allkeys-lru
OK
127.0.0.1:6379> CONFIG REWRITE
OK
五、總結 🎉
理解和選擇對的 Redis 淘汰策略,對于優化性能、保證服務穩如老狗 🐕 以及滿足業務需求都超級重要!一定要根據你的應用特點和數據訪問模式來選型,并通過監控 Redis 內存 (INFO memory
) 和淘汰情況 (INFO stats
里的 evicted_keys
) 來看看效果怎么樣。記住,只有設置了 maxmemory
,淘汰策略才會開始工作哦!😉