一、key的過期刪除策略
????????原由:一般情況下,在使用redis作緩存,對k設置過期時間,當過期時間到后,k還是占用內存的,并沒有從內存中移除。
1.定時刪除
????????在設置key的過期時間的同時,為該key創建一個定時器,讓定時器在key的過期時間來臨時,對key進行刪除
????????優點:保證內存被盡快釋放
????????缺點:1>若過期key很多,刪除這些key會占用很多的CPU時間,在CPU時間緊張的情況下,CPU不能把所有的時間用來做要緊的事兒,還需要去花時間刪除這些key。
??????????????????2>定時器的創建耗時,若為每一個設置過期時間的key創建一個定時器(將會有大量的定時器產生),性能影響嚴重
2.惰性刪除
????????key過期的時候不刪除,每次從數據庫獲取key的時候去檢查是否過期,若過期,則刪除,返回null。
????????優點:刪除操作只發生在從數據庫取出key的時候發生,而且只刪除當前key,所以對CPU時間的占用是比較少的,而且此時的刪除是已經到了非做不可的地步.
????????缺點:若大量的key在超出超時時間后,很久一段時間內,都沒有被獲取過,那么可能發生內存泄露(無用的垃圾占用了大量的內存)
3.定期刪除
????????每隔一段時間執行一次刪除過期key操作
????????定期任務(serverCron)任務每隔一段時間就會運行一次,其中就包含清理過期key的任務,運行頻率由配置文件中的hz參數來控制,取值范圍1~500,默認是10,代表每秒運行10次。清理過程如下:
- 遍歷所有的db
- 從db中設置了過期時間的key的集合中隨機檢查20個key
- 刪除檢查中發現的所有過期key
????????如果檢查結果中25%以上的key已過期,則繼續重復執行步驟2-3,否則繼續遍歷下一個db,調大hz將會提高redis定期任務的執行頻率,如果你的redis中包含很多過期key的話,可以考慮將這個值調大,但要注意同時也會增加CPU的壓力,redis作者建議這個值不要超過100。
????????優點: 1>通過限制刪除操作的時長和頻率,來減少刪除操作對CPU時間的占用--處理"定時刪除"的缺點.
?????????????????2>定期刪除過期key--處理"惰性刪除"的缺點
????????缺點:1>在內存友好方面,不如"定時刪除"
??????????????????2>在CPU時間友好方面,不如"惰性刪除"
redis是怎么采用的過期策略
- 惰性刪除+定期刪除
- 惰性刪除流程:在進行get或setnx等操作時,先檢查key是否過期,若過期,刪除key,然后執行相應操作;若沒過期,直接執行相應操作
- 定期刪除流程:遍歷每個數據庫,檢查當前庫中的指定個數個key(默認是每個庫檢查20個key,注意相當于該循環執行20次,循環體時下邊的描述),如果當前庫中沒有一個key設置了過期時間,直接執行下一個庫的遍歷,隨機獲取一個設置了過期時間的key,檢查該key是否過期,如果過期,刪除key,判斷定期刪除操作是否已經達到指定時長,若已經達到,直接退出定期刪除。
二、內存淘汰機制
1. 不進行數據淘汰(No Eviction)
noeviction
:- 行為: 這是 Redis 的默認策略。當內存達到上限時,Redis 不會主動淘汰任何數據。
- 結果: 如果此時有寫入請求(如?
SET
,?LPUSH
?等),Redis 會返回錯誤(通常是?(error) OOM command not allowed when used memory > 'maxmemory'
)。讀取請求(如?GET
)仍然可以正常執行。 - 適用場景: 適用于數據量小且能精確控制內存,或者絕對不允許丟失任何數據的場景。需要應用程序自己處理內存溢出錯誤。
2. 基于過期時間的淘汰策略(針對設置了?expire
?的 Key)
這些策略只會在設置了過期時間(TTL)的鍵中選擇淘汰目標。
-
volatile-lru
:- 行為: 從設置了過期時間的鍵中,使用最近最少使用(Least Recently Used, LRU)算法淘汰最久未被訪問的鍵。
- 特點: 優先保證長期未訪問的過期數據被淘汰,保留了經常訪問的熱點過期數據。
- 適用場景: 緩存場景,其中大部分需要緩存的數據都設置了過期時間,希望保留熱點數據。
-
volatile-lfu
:- 行為: 從設置了過期時間的鍵中,使用最少頻率使用(Least Frequently Used, LFU)算法淘汰訪問頻率最低的鍵。
- 特點: LFU 算法比 LRU 更能反映數據的長期訪問熱度,能更好地保留高頻訪問的數據,即使它們最近一次訪問不是最新的。
- 適用場景: 緩存場景,數據訪問模式存在明顯的熱點,且希望更精確地保留高頻訪問的過期數據。需要 Redis 4.0+。
-
volatile-ttl
:- 行為: 從設置了過期時間的鍵中,淘汰剩余生存時間(TTL)最短的鍵。
- 特點: 優先淘汰即將過期的數據。
- 適用場景: 當希望數據盡可能在過期前被使用,但內存緊張時優先清理“快過期”的數據。效果可能不如?
volatile-lru
?或?volatile-lfu
?理想。
-
volatile-random
:- 行為: 從設置了過期時間的鍵中,隨機選擇一個鍵進行淘汰。
- 特點: 實現簡單,性能開銷小,但淘汰沒有基于訪問模式,可能淘汰掉熱點數據。
- 適用場景: 對淘汰算法要求不高,或者訪問模式非常隨機,且所有過期鍵價值相當的場景。
3. 基于所有鍵的淘汰策略(針對所有 Key,無論是否設置過期時間)
這些策略會考慮數據庫中的所有鍵(無論是否設置了過期時間)。
-
allkeys-lru
:- 行為: 在所有鍵中,使用最近最少使用(LRU)算法淘汰最久未被訪問的鍵。
- 特點: 會淘汰長期未訪問的任何數據,包括沒有設置過期時間的持久化數據。
- 適用場景: 緩存場景,其中部分數據可能未設置過期時間,但仍希望基于訪問熱度進行淘汰。這是非常常用的緩存策略。
-
allkeys-lfu
:- 行為: 在所有鍵中,使用最少頻率使用(LFU)算法淘汰訪問頻率最低的鍵。
- 特點: 同樣能更好地保留高頻訪問的任何數據。
- 適用場景: 緩存場景,數據訪問熱點明顯,希望最精確地保留高頻訪問數據,無論其是否過期。需要 Redis 4.0+。
-
allkeys-random
:- 行為: 在所有鍵中,隨機選擇一個鍵進行淘汰。
- 特點: 實現簡單,性能開銷最小,但完全不考慮訪問模式,可能淘汰掉重要的持久化數據。
- 適用場景: 數據價值相對均勻,或者對數據丟失不敏感,追求極致性能的場景。
三、其他模塊對過期鍵的處理
生成RDB文件時
- 執行?save?或?bgsave?時 ,數據庫鍵空間中的過期鍵不會被保存在RDB文件中。
載入RDB文件時
- master 載入RDB時,文件中的未過期的鍵會被正常載入,過期鍵則會被忽略。
- slave 載入 RDB 時,文件中的所有鍵都會被載入,當同步進行時,會和Master 保持一致。
AOF 文件寫入時
- 數據庫鍵空間的過期鍵的過期但并未被刪除釋放的狀態會被正常記錄到AOF文件中,當過期鍵發生釋放刪除時,DEL也會被同步到?AOF文件中去。
主從同步過期key
- Master?刪除過期key之后,會向所有slave?服務器發送一個DEL命令,從服務器收到之后,會刪除這些Key。
- Slave?在被動的讀取過期鍵時,不會做出操作,而是繼續返回該鍵,只有當Master?發送?DEL?通知來,才會刪除過期鍵,這是統一、中心化的鍵刪除策略,保證主從服務器的數據一致性。
?推薦一個非常好用的工具集合:在線工具集合 - 您的開發助手