1. 程式人生 > 其它 >Redis快取淘汰策略

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