Redis的內存淘汰策略詳解

Redis佔用內存

Redis作爲內存型數據庫,在業務量過大的情況下,會出現內存不夠的情況(達到[maxmemory]設置值),當然機器內存足夠強大,數據可承受範圍會更大,但是這不是解決問題的方法。

Redis提供了兩種解決方法:

  • 設置key的超時時間
  • LRU算法

設置數據的超時時間(TTL)

關於設置數據的超時時間這個方法,是我們經常用到的,同時設置超時時間還可以在某些場景下滿足我們的業務需要:

  • 驗證碼的失效時間
  • 用戶token的失效時間
  • ......

但是有沒有想過TTL的過期策略是什麼呢?

Redis的過期策略

redis的過期策略分爲:定期刪除 和 惰性刪除

定期刪除

Redis會將每個設置了過期時間的 key 放入到一個獨立的字典中,以後會定期遍歷這個字典來刪除到期的 key。

Redis 默認會每秒進行十次過期掃描(100ms一次),過期掃描不會遍歷過期字典中所有的 key,而是採用了一種簡單的貪心策略:

  1. 從過期字典中隨機20個key
  2. 刪除這 20 個 key 中已經過期的 key
  3. 如果過期的 key 比率超過 1/4,那就重複步驟 1

這裏隨機抽取就是爲了在數據量過大的情況下,遍歷大量的key,給CPU增加負擔

惰性刪除

惰性刪除就是在客戶端訪問這個key的時候,redis對key的過期時間進行檢查,如果過期了就立即刪除,不會給你返回任何東西。通常情況下我們在日常的使用過程中查詢已經過期的key,是比較容易觸發該機制的。

定期刪除是從比較大的層面做key的過期刪除,因爲其隨機性,導致會有過期key不能及時刪除的情況發生,惰性刪除是在某些情況下對定期刪除的一種彌補策略。

LRU

什麼是LRU算法?

  1. 新增key value的時候首先在鏈表結尾添加Node節點,如果超過LRU設置的閾值就淘汰隊頭的節點並刪除掉HashMap中對應的節點。
  2. 修改key對應的值的時候先修改對應的Node中的值,然後把Node節點移動隊尾。
  3. 訪問key對應的值的時候把訪問的Node節點移動到隊尾即可。

Redis使用的是近似LRU算法:近似LRU算法通過隨機採樣法淘汰數據,每次隨機出5(默認)個key,從裏面淘汰掉最近最少使用的key,可以通過maxmemory-samples參數修改採樣數量: 例:maxmemory-samples 10 maxmenory-samples配置的越大,淘汰的結果越接近於嚴格的LRU算法,但是同時對內存的消耗也越大。

Redis使用近似LRU算法,在基本滿足策略需要的情況,儘可能的降低了內存的消耗,CPU的佔用,在硬件滿足的情況的下,也可以通過maxmemory-samples的調整,無線接近於標準LRU算法。

Redis爲了實現近似LRU算法,給每個key增加了一個額外增加了一個24bit的字段,用來存儲該key最後一次被訪問的時間。

Redis3.0對近似LRU算法進行了一些優化。新算法會維護一個候選池(大小爲16),池中的數據根據訪問時間進行排序,第一次隨機選取的key都會放入池中,隨後每次隨機選取的key只有在訪問時間小於池中最小的時間纔會放入池中,直到候選池被放滿。當放滿後,如果有新的key需要放入,則將池中最後訪問時間最大(最近被訪問)的移除。當需要淘汰的時候,則直接從池中選取最近訪問時間最小(最久沒被訪問)的key淘汰掉就行。

內存淘汰策略

1. noeviction:當內存使用超過配置的時候會返回錯誤,不會驅逐任何鍵

2. allkeys-lru:加入鍵的時候,如果過限,首先通過LRU算法驅逐最久沒有使用的鍵

3. volatile-lru:加入鍵的時候如果過限,首先從設置了過期時間的鍵集合中驅逐最久沒有使用的鍵

4. allkeys-random:加入鍵的時候如果過限,從所有key隨機刪除

5. volatile-random:加入鍵的時候如果過限,從過期鍵的集合中隨機驅逐

6. volatile-ttl:從配置了過期時間的鍵中驅逐馬上就要過期的鍵

7. volatile-lfu:從所有配置了過期時間的鍵中驅逐使用頻率最少的鍵(Reidis4之後)

8. allkeys-lfu:從所有鍵中驅逐使用頻率最少的鍵(Reidis4之後)

LFU

LFU是在Redis4.0後出現的,LRU的最近最少使用實際上並不精確,考慮下面的情況,如果在|處刪除,那麼A距離的時間最久,但實際上A的使用頻率要比B頻繁,所以合理的淘汰策略應該是淘汰B。LFU就是爲應對這種情況而生的。

A~~A~~A~~A~~A~~A~~A~~A~~A~~A~~~|

B~~~~~B~~~~~B~~~~~B~~~~~~~~~~~~B|

 

參考:

https://zhuanlan.zhihu.com/p/105587132

https://www.cnblogs.com/vegetableDD/p/11890570.html

https://www.bilibili.com/video/BV1Cb411j7RA?p=8

https://segmentfault.com/a/1190000017555834