Redis快取淘汰策略
Redis快取淘汰策略
前言
長期將Redis作為快取使用,難免會遇到記憶體空間儲存瓶頸,當Redis記憶體超出實體記憶體限制時,記憶體資料就會與磁碟產生頻繁交換,使Redis效能急劇下降。此時如何淘汰無用資料釋放空間,儲存新資料就變得尤為重要了。解決這個問題就涉及到快取系統的一個重要機制,即快取資料的淘汰機制。
一、淘汰機制實現步驟
簡單來說,資料淘汰機制包括兩步
1、根據一定的策略,篩選出對應用訪問來說“不重要”的資料;
2、將這些資料從快取中刪除,為新來的資料騰出空間,
Redis3.0版本支援的淘汰策略有6種,自Redis 4.0版本開始新增volatile-lfu和allkeys-lfu這兩種策略。
二、淘汰機制分類
1、按照是否會進行資料淘汰分類
1)不進行資料淘汰的策略,只有 noeviction 這一種。
2)會進行淘汰的 7 種其他策略。
2、根據淘汰候選資料集的範圍分類
1)在設定了過期時間的資料中進行淘汰,包括 volatile-random、volatile-ttl、volatile-lru、volatile-lfu(Redis 4.0 後新增)四種。
2)在所有資料範圍內進行淘汰,包括 allkeys-lru、allkeys-random、allkeys-lfu三種。
三、淘汰策略詳情
預設情況下,Redis 在使用的記憶體空間超過 maxmemory 值時,並不會淘汰資料,也就是設定的 noeviction 策略。對應到 Redis 快取,也就是指,一旦快取被寫滿了,再有寫請求來時,Redis 不再提供服務,而是直接返回錯誤。
1、noevction:一旦快取被寫滿了,再有寫請求來時,Redis 不再提供服務,而是直接返回錯誤。Redis 用作快取時,實際的資料集通常都是大於快取容量的,總會有新的資料要寫入快取,這個策略本身不淘汰資料,也就不會騰出新的快取空間,我們不把它用在 Redis 快取中。
2、volatile-ttl 在篩選時,會針對設定了過期時間的鍵值對,根據過期時間的先後進行刪除,越早過期的越先被刪除。
3、volatile-random 就像它的名稱一樣,在設定了過期時間的鍵值對中,進行隨機刪除。
4、volatile-lru 會使用 LRU 演算法(下文具體介紹)篩選設定了過期時間的鍵值對。
5、volatile-lfu 會使用 LFU 演算法(下文具體介紹)選擇設定了過期時間的鍵值對。
6、allkeys-random 策略,從所有鍵值對中隨機選擇並刪除資料。
7、allkeys-lru 策略,使用 LRU 演算法在所有資料中進行篩選。
8、allkeys-lfu 策略,使用 LFU 演算法在所有資料中進行篩選。
四、淘汰演算法
1、LRU演算法
LRU(Least recently used,最近最少使用)演算法根據資料的歷史訪問記錄來進行淘汰資料,其核心思想是“如果資料最近被訪問過,那麼將來被訪問的機率也更高”。
在 Redis 中,LRU 演算法被做了簡化,以減輕資料淘汰對快取效能的影響。具體來說,Redis 預設會記錄每個資料的最近一次訪問的時間戳(由鍵值對資料結構 RedisObject 中的 lru 欄位記錄)。然後,Redis 在決 定淘汰的資料時,第一次會隨機選出 N 個數據,把它們作為一個候選集合。接下來,Redis 會比較這 N 個數據的 lru 欄位,把 lru 欄位值最小的資料從快取中淘汰出去。
Redis 提供了一個配置引數 maxmemory-samples,這個引數就是 Redis 選出的資料個數 N。例如,我們執行如下命令,可以讓 Redis 選出 100 個數據作為候選資料集:
CONFIG SET maxmemory-samples 100
當需要再次淘汰資料時,Redis 需要挑選資料進入第一次淘汰時建立的候選集合。這兒的挑選標準是:能進入候選集合的資料的 lru 欄位值必須小於候選集合中最小的 lru 值。當有新資料進入候選資料集後,如果候選資料集中的資料個數達到了 maxmemory-samples,Redis 就把候選資料集中 lru 欄位值最小的資料淘汰出去。
這樣一來,Redis 快取不用為所有的資料維護一個大連結串列,也不用在每次資料訪問時都移動連結串列項,提升了快取的效能。
LRU演算法有一個問題就是,當應用對大量的資料進行一次全體讀取,每個資料都會被讀取,而且只會被讀取一次。此時,因為這些被查詢的資料剛剛被訪問過,所以 lru 欄位值都很大。而其他的熱點資料就會被淘汰掉。
2、LFU演算法
Redis 從 4.0 版本開始增加了 LFU 淘汰策略。與 LRU 策略相比,LFU 策略中會從兩個維度來篩選並淘汰資料:
1、資料訪問的時效性(訪問時間離當前時間的遠近)
2、資料的被訪問次數。
LFU 快取策略是在 LRU 策略基礎上,為每個資料增加了一個計數器,來統計這個資料的訪問次數。當使用 LFU 策略篩選淘汰資料時,首先會根據資料的訪問次數進行篩選,把訪問次數最低的資料淘汰出快取。如果兩個資料的訪問次數相同,LFU 策略再比較這兩個資料的訪問時效性,把距離上一次訪問時間更久的資料淘汰出快取。
應用對大量的資料進行一次全體讀取,因為這些資料不會被再次訪問,所以它們的訪問次數不會再增加。因此,LFU 策略會優先把這些訪問次數低的資料淘汰出快取。就解決了上面提到的LRU存在的問題。
3、TTL演算法
Redis 資料集資料結構中儲存了鍵值對過期時間的表,即 redisDb.expires。與 LRU 資料淘汰機制類似,TTL 資料淘汰機制中會先從過期時間的表中隨機挑選幾個鍵值對,取出其中 ttl 比較小的鍵值對淘汰。同樣,TTL淘汰策略並不是面向所有過期時間的表中最快過期的鍵值對,而只是隨機挑選的幾個鍵值對。
4、隨機演算法
在隨機淘汰的場景下獲取待刪除的鍵值對,隨機找hash桶再次hash指定位置的dictEntry即可。
五、Redis.conf中配置淘汰策略
1 #設定Redis 記憶體大小的限制,我們可以設定maxmemory ,當資料達到限定大小後,會選擇配置的策略淘汰資料 2 3 maxmemory 300mb 4 5 6 7 #設定Redis的淘汰策略。 8 9 maxmemory-policy volatile-lru
Redis中的淘汰機制都是幾近於演算法實現的,主要從效能和可靠性上做平衡,所以並不是完全可靠,所以開發者們在充分了解Redis淘汰策略之後還應在平時多主動設定或更新key的expire時間,主動刪除沒有價值的資料,提升Redis整體效能和空間。
參考連結:
https://www.jianshu.com/p/3981610b645a