當
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-lru
,volatile-random
和volatile-ttl
策略的行爲類似於noeviction
。
選擇正確的淘汰策略很重要,具體取決於應用程序的訪問方式,也可以在應用程序運行時在運行時重新配置該策略,爲了方便調整設置,可以使用Redis
的INFO
命令來監控緩存未命中和命中的數量。
一般而言,根據經驗:
- 使用
allkeys-lru
策略。如果你希望request
呈指數分佈,也就是說,你希望對於某些元素的訪問比其他元素多得多。 - 使用
allkeys-random
。如果你希望對所有的key進行行週期性第連續訪問,或者當你期望分佈是統一的(所有元素以相同的概率被訪問)。 - 使用
volatile-ttl
。如果你希望能夠在創建緩存對象時通過使用不同的TTL
值向Redis
表明哪些key是最佳過期候選者。
當你要使用單個Redis
實例進行緩存並擁有一些持久化的key時,volatile-lru
和volatile-random
策略相當有用。 但是,最好運行兩個Redis
實例來解決此問題。
值得注意的是
,爲一個key設置過期時間要耗費內存,因此像allkeys-lru
這樣的策略能提高內存效率,因爲不需要爲那個在內存壓力下需要被刪除的key設置過期時間。
3. 淘汰策略如何工作
理解淘汰策略的工作工程時很關鍵的。
client
運行新命令,從而添加更多數據。Redis
會檢查內存使用情況,如果大於maxmemory
限制,則會根據策略刪除key。- 執行新命令,依此類推。
所以內存使用量會一直在maxmemory
上下徘徊,如果某個命令要求添加一個很大的數據很可能造成redis
使用的內存明顯超過了maxmemory
限制。
4. 近似LRU算法
redis
的LRU
沒有嚴格的實現LRU
,這意味着redis
不是淘汰最佳(最久沒訪問)的數據。。Redis
對LRU
算法進行近似處理,方法是對少量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淘汰算法。
LFU
和LRU
類似也是一種概率計算,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緩存