1. 程式人生 > 其它 >Redis中LRU演算法的實現

Redis中LRU演算法的實現

  • 整體思路:首先定義一個淘汰池,這個淘汰池是一個數組(大小為16),然後觸發淘汰時會根據配置的淘汰策略,先從符合條件的key中隨機取樣選出5(可在配置檔案中配置)個key,計算其空閒時間,如果Pool還沒有滿或者比Pool中的最小空閒時間Key大的話,就將空閒時間小的Key從Pool中移除,將Key加入到Pool中。每次取樣之後更新這個淘汰池,讓這個淘汰池裡保留的總是那些隨機取樣出的key中空閒時間最長的那部分key。需要刪除key時,只需將淘汰池中空閒時間最長的key刪掉即可。

  • LRU時鐘概述:Redis 在實現上引入了一個 LRU 全域性時鐘來代替 unix 時間戳,其基本單位是1000ms,LRU時鐘在1000ms內的時間戳都是一樣的,LRU全域性時鐘的更新通過serverCron時間事件回撥函數週期性更新(預設每100ms執行一次)來實現。

  • 物件的空閒時間的計算:每個物件的在建立或每次被訪問都會記錄下當前伺服器的 LRU 時鐘(由鍵值對資料結構 RedisObject 中的24 bits的 lru 欄位記錄),然後用伺服器的 LRU 時鐘減去物件本身的時鐘,得到的就是這個物件沒有被訪問的時間間隔(也稱空閒時間),空閒時間最大的就是需要淘汰的物件。

  • LRU執行的時機:每一次處理客戶端命令的時候

  • 執行過程:

    • 伺服器維護一個大小為16的淘汰池(陣列實現),按照空閒時間從小到大排序。

    • 首先評估當前記憶體的使用情況,使用的記憶體容量是否超過maxmemory配置的值。

      • 如果沒有超過,返回

      • 如果超過閾值,那麼呼叫函式迴圈淘汰資料釋放記憶體。

    • 選取待淘汰的鍵值對

      • 如果淘汰策略是allkeys_lru,就從全部鍵值對中取樣

      • 如果淘汰策略是volitile_lru,就從設定了TTL的鍵值對中取樣

      • 隨機選出maxmemory-samples(預設是5)個鍵值對

    • 更新淘汰池

      • 對於上一步取樣的每一個待淘汰鍵值對,如果可以滿足以下條件之一,就可以插入到淘汰池當中:

        • 淘汰池沒有滿

        • 淘汰池中存在鍵值對的空閒時間小於取樣的待淘汰鍵值對

    • 選擇被淘汰的鍵值對並刪除

      • 淘汰池裡面的資料都是按照空閒時間從小到大來排序的,所以從淘汰池陣列的末尾開始遍歷,然後找到第一個非空的資料,然後根據Redis server的惰性刪除配置,執行同步刪除或非同步刪除,終止遍歷。

    • 判斷是否再次迴圈

      至此淘汰了一個key,若此時沒有達到待釋放空間,則再次取樣、更新、刪除。

參考部落格:

https://mp.weixin.qq.com/s/kWkoTO-0iOsSPsYhFRiVHA

https://mp.weixin.qq.com/s/x6NyYJdr9yQdXIY-V9iY2A

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