初識 將Redis作爲LRU緩存


Redis用作緩存時,通常很容易在添加新數據的同時移除舊數據。 此行爲在開發者社區中是衆所周知的,因爲它是memcached system 的默認行爲。

LRU(Least Recently Used,最近最少使用),將最近最少使用的數據刪除掉。

Redis 4.0 開始引入了LFU(Least Frequntly Used,最不常用)淘汰策略。

1. Maxmemory配置

Redis maxmemory 用於將內存使用限制爲某一固定量。該配置常在名爲redis.conf 的文件中,或者在運行時(runtime)使用CONFIG SET命令進行配置。

例如,爲了配置內存限制爲100 MB,可以在 redis.conf 文件中使用以下設置。

maxmemory 100mb

maxmemory 設置爲零則沒有內存限制。 這是64位系統的默認行爲,而32位系統使用3GB的隱式內存限制。

當達到限定的內存量時,可以選擇不同的策略。 只有當 Redis 執行的命令要使用更多的內存,Redis 纔會返回error,或者Redis刪除一些舊數據,以便在每次添加新數據時返回到指定的限制。

2. 淘汰策略

在配置文件裏使用 maxmemory-policy 命令可以指定以下淘汰策略:

noeviction:在達到內存限制並且client嘗試執行可能導致使用更多內存的命令時返回錯誤。
allkeys-lru:嘗試先刪除LRU的key。
volatile-lru:嘗試先刪除LRU的key,要求刪除的這個key必須已經過期。
allkeys-random:隨機刪除key。
volatile-random:隨機刪除key,要求刪除的這個key必須已經過期。
volatile-ttl:刪除已經過期的key,嘗試先刪除較短生存時間(TTL)的key。

如果執行這些策略時,發現沒有與條件相匹配的key,則volatile-lruvolatile-randomvolatile-ttl策略的行爲類似於noeviction

選擇正確的淘汰策略很重要,具體取決於應用程序的訪問方式,也可以在應用程序運行時在運行時重新配置該策略,爲了方便調整設置,可以使用RedisINFO 命令來監控緩存未命中和命中的數量。

一般而言,根據經驗:

  • 使用allkeys-lru策略。如果你希望request呈指數分佈,也就是說,你希望對於某些元素的訪問比其他元素多得多。
  • 使用allkeys-random。如果你希望對所有的key進行行週期性第連續訪問,或者當你期望分佈是統一的(所有元素以相同的概率被訪問)。
  • 使用volatile-ttl。如果你希望能夠在創建緩存對象時通過使用不同的TTL值向Redis 表明哪些key是最佳過期候選者。

當你要使用單個Redis實例進行緩存並擁有一些持久化的key時,volatile-lruvolatile-random策略相當有用。 但是,最好運行兩個Redis實例來解決此問題。

值得注意的是,爲一個key設置過期時間要耗費內存,因此像allkeys-lru這樣的策略能提高內存效率,因爲不需要爲那個在內存壓力下需要被刪除的key設置過期時間。

3. 淘汰策略如何工作

理解淘汰策略的工作工程時很關鍵的。

  • client 運行新命令,從而添加更多數據。
  • Redis會檢查內存使用情況,如果大於maxmemory限制,則會根據策略刪除key。
  • 執行新命令,依此類推。

所以內存使用量會一直在maxmemory上下徘徊,如果某個命令要求添加一個很大的數據很可能造成redis使用的內存明顯超過了maxmemory限制。

4. 近似LRU算法

redisLRU沒有嚴格的實現LRU,這意味着redis不是淘汰最佳(最久沒訪問)的數據。。RedisLRU算法進行近似處理,方法是對少量key進行採樣,然後從採樣的key中刪除掉訪問時間最早的key。

3.0以後redis會使用備選池做淘汰,提升了性能,準確性更高,更接近LRU算法(代碼裏提升性能很明顯,準確率更高這點看不出來,可能官方做統計得出的結論)。可以設置樣本大小調整算法的準確率。

maxmemory-samples 5

Redis之所以不使用真正的LRU實現,是因爲它佔用更多內存(要遍歷排序,會慢很多)。

5. LFU模式

從4.0開始redis引入了一個新的淘汰模型LFU(Least Frequently Used)。一些情況下這個模型在命中率上更會準確。LFU會統計數據的使用率,使用率低的會被淘汰,使用率高的留下。LRU會保留最近訪問了但是平常訪問率很低的數據,風險就是淘汰了一個平常訪問率高但是最近沒訪問的數據。 LFU不會存在這樣的問題,所以LFU更適用於各種不同的訪問模型。LFU策略配置如下:

  • volatile-lfu:在設置了過期時間的數據裏使用近似LFU淘汰算法。
  • allkeys-lfu:在所有的數據上使用LFU淘汰算法。

LFULRU類似也是一種概率計算,LFU使用一個叫morris counter的概率統計方法,一個數據只使用幾個比特。和一個叫過期時間(decay period)的數結合使用。統計值(counter)隨着時間減小。LFU也是使用採樣的方式淘汰數據。LFU有更多的調整選項,4.0默認的配置

  • 一百萬訪問量會使統計值(counter)變爲最大
  • 衰敗期是一分鐘

這些是經過測試比較好用的,用戶也可以自己設置。配置命令如下:

lfu-log-factor 10
lfu-decay-time 1

一個比較特殊的用法是衰敗期設置成0,每次統計都會衰敗,這是個比較少用的方法。指數因子用來指定多大的訪問量會是統計值變爲最大,統計值範圍0-255。指數因子越大需要越多的訪問量使統計值變爲最大,指數因子越小訪問量低的時候分辨率越高。

+--------+------------+------------+------------+------------+------------+
| factor | 100 hits   | 1000 hits  | 100K hits  | 1M hits    | 10M hits   |
+--------+------------+------------+------------+------------+------------+
| 0      | 104        | 255        | 255        | 255        | 255        |
+--------+------------+------------+------------+------------+------------+
| 1      | 18         | 49         | 255        | 255        | 255        |
+--------+------------+------------+------------+------------+------------+
| 10     | 10         | 18         | 142        | 255        | 255        |
+--------+------------+------------+------------+------------+------------+
| 100    | 8          | 11         | 49         | 143        | 255        |
+--------+------------+------------+------------+------------+------------+

6. 參考文獻

Redis 官方文檔 Using Redis as an LRU cache
LRU緩存機制
用redis當作LRU緩存

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章