上回在《Redis 資料過期了會被立馬刪除麼?》說到如果過期的資料太多,定時刪除無法刪除完全(每次刪除完過期的 key 還是超過 25%),同時這些 key 再也不會被客戶端請求,就無法走惰性刪除,記憶體被打滿會怎樣?
答案是走記憶體淘汰機制。
故事從一個叫 Redis 帝國的三公九卿官職說起……
在 Redis 帝國中,整個帝國的國法、家法和軍法等都記錄在 redis.conf
中,它控制著整個帝國的執行。
公務員佔用的國家地盤資源大小限定由名叫「maxmemory」的司法官員制定,一共有兩種方式實現:
- 在執行時使用
CONFIG SET maxmemory 4gb
指定帝國官職人員最大地盤資源為 4GB; - 將
maxmemory 4gb
法令記錄到redis.conf
「法典」中,在帝國運轉指定使用該「法典」執行。
需要注意的是,如果 maxmemory
為 0 ,在 64
位「空間」上則沒有限制,而 32
位「空間」則有 3GB
的隱式限制。
Redis 記憶體淘汰策略
設定了帝國官職地盤資源限制,每年選拔新人就會導致沒有地盤資源可以使用怎麼辦?如何選擇一些公務員淘汰?
在 Redis 4.0 時代,一共有 6 種淘汰策略,之後,又新增了 2 中策略。
總體上我們可以根據是否需要淘汰可以分為兩大類:
- 不執行淘汰策略,
noeviction
; - 根據不同法則淘汰的其他 7 中策略。
noeviction 不退伍策略
預設情況下,資源超過 maxmemory
的值也不會執行淘汰,不允許新人加入。
關係戶啊這是,皇親國戚,永久 vip 啊喂。
隨著官職人員的新增,由於不會淘汰,資源容量遲早會滿。滿了以後,當有「新人」想要進來的時候,Redis 直接返回錯誤,並罷工。
秀,真是任性。
各式各樣的淘汰策略
剩下的 7 種策略還可以根據淘汰的候選集合和淘汰範圍分為兩大類:
-
對有設定任職過期時間的職員進行淘汰,沒有設定任職過期時間的不會淘汰,淘汰策略如下:
- volatile-lru:淘汰最近最少上一線幹活的人員;
- volatile-lfu:4.0 之後新增的策略,淘汰上一線幹活次數最少的人員;
- volatile-random:隨機淘汰,騰出坑位給新人;
- volatile-ttl:淘汰設定了任期時間的公務員,誰最接近任期時間就先淘汰誰。
-
對所有型別人員淘汰,不管是永久 vip 的皇親國戚還是設定了任職過期時間的人員。
- allkeys-lru:淘汰最近最少上一線幹活的職員;
- allkeys-lfu:淘汰最少上一線幹活的公務員;
- allkeys-random:隨機淘汰職員,為新兵騰出空位。
故事到這裡就結束了,接下來「碼哥」分享下在實際 Redis 中如何選擇合適的淘汰策略和設定最佳快取大小給大家。
淘汰執行過程如下圖所示:
-
客戶端傳送新命令到服務端;
-
服務端收到客戶端命令,Redis 檢查記憶體使用情況,如果大於
maxmemory
限制,則根據策略驅逐資料。 -
執行新命令。
allkeys-lru 使用場景
假如你的應用存在明顯的冷熱資料區別,根據經驗推薦你使用這個策略,充分利用 LRU 演算法把最近最常訪問的資料保留,有限的記憶體提高訪問效能。
allkeys-random 使用場景
假如資料沒有明顯的冷熱分別,所有的資料分佈查詢比較均衡,這些資料都會被隨機查詢,那就使用 allkeys-random 策略,讓其隨機選擇淘汰資料。
volatile-lru 使用場景
業務場景有一些資料不能刪除,比如置頂新聞、視訊,這時候我們為這些資料不設定過期時間,這樣的話資料就不會被刪除,該策略就會去根據 LRU 演算法去淘汰哪些設定了過期時間且最近最少被訪問的資料。
有一個點需要注意下,為 key 執行 expire 設定過期時間會消耗一些記憶體,所以使用 allkeyds-lru
會提高記憶體效率。
將需要持資料不能刪除的和全都可以淘汰資料的業務系統分別使用不同的 Redis 例項叢集是更好的方案。
針對業務場景有一些資料不能刪除的使用 volatile-lru
策略,另一類則可以使用 allkyes-lru 或者 allkeys-random
。
Redis 容量設定多大合適
快取並不是越大越好,用最小的代價去獲得最高的收益才是老闆想要的。
資料訪問有區域性性,根據「二八原理」:通常 20% 的資料能支撐 80% 的訪問請求。
所以我們可不可以把快取容量大小設定為總資料量的 20%?
當然,不能這麼絕對,這是理想狀態。因為可能存在一些個性化需求,不同的使用者訪問的資料可能差別很大,不完全具備「二八原理」。
我們應當結合實際的訪問特點和成本來綜合評估。根據經驗建議將容量設定成總資料量的 15%~30%。
碼哥,其他淘汰規則比較簡單,volatile-lru 和 volatile-lfu 則比較複雜,他們的演算法是怎樣的?
volatile-lru 使用了 LRU 演算法,淘汰最近最少使用的資料。而volatile-lfu 使用了 LFU 演算法,它在 LRU 演算法基礎上同時考慮了資料的時效性和訪問頻率,最少訪問的 key 會被刪除。
至於具體演算法細節,我們下回分解。一次性太多的話大家容易在知識的海洋裡裡嗆水。
現在的文章閱讀量越來越低
大家可以在評論區叫我一聲靚仔麼?
不想叫我靚仔的可以幫我點個贊和在看麼?
參考資料
1.https://redis.io/docs/manual/eviction/
2.Redis 核心技術與實戰