Redis中LRU演算法的實現
-
-
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的惰性刪除配置,執行同步刪除或非同步刪除,終止遍歷。
-
-
判斷是否再次迴圈
參考部落格:
https://mp.weixin.qq.com/s/kWkoTO-0iOsSPsYhFRiVHA
https://mp.weixin.qq.com/s/x6NyYJdr9yQdXIY-V9iY2A
https://zhuanlan.zhihu.com/p/450102782