Redis技術知識總結之三——Redis數據淘汰機制

接上篇《Redis技術知識總結之二——Redis線程模型》

三. Redis 的數據淘汰機制

3.1 Redis 的數據淘汰策略

當 Redis 內存超出物理內存限制時,爲了保持高效的可用性,Redis 需要對內存中部分數據進行淘汰。Redis 早起版本使用的數據淘汰策略是 LRU (Least Recently Used,最近最少使用) 策略,LRU 策略是基於最近訪問時間進行排序、淘汰的。後來加入了 LFU (Least Frequency Used,最近最低頻率) 策略。
Redis 主要使用的還是 LRU 策略。

  • noeviction: 可以繼續讀請求,不可以進行寫請求。
    • 返回錯誤當內存限制達到並且客戶端嘗試執行會讓更多內存被使用的命令(大部分的寫入指令,但 DEL 和幾個例外);
    • 默認淘汰策略。
  • volatile-lru: 嘗試回收最少使用的鍵(LRU),但僅限於在設置了過期時間的鍵,使得新添加的數據有空間存放。
  • volatile-random: 回收隨機的鍵使得新添加的數據有空間存放,但僅限於在設置了過期時間的鍵
  • volatile-ttl: 回收設置了過期時間的鍵,淘汰策略是優先回收剩餘時間 (TTL) 較短的鍵,使得新添加的數據有空間存放。
  • allkeys-lru: 對全部集合進行回收,嘗試回收最少使用的鍵 (LRU),使得新添加的數據有空間存放。
  • allkeys-random: 對全部集合進行回收,回收隨機的鍵使得新添加的數據有空間存放。
  • volatile-lfu: 對設置了過期時間的鍵進行 LFU 策略的過期篩選;
  • allkeys-lfu: 對全部的鍵進行 LFU 策略的過期篩選;

3.2 LRU 策略

Redis 的數據都是由 key-value 形式構成的,在實現 LRU 的內存淘汰機制時,除了 key-value,LRU 還需要維護一個列表,鏈表尾部的數據是最少被訪問的數據。列表按照最近訪問時間進行排序。當內存達到物理內存限制觸發 LRU 回收時,對鏈表尾部的 k-v 進行回收。

但 Redis 的 LRU 並不是這樣執行的,Redis 使用了一種近似 LRU 算法。對於所有 Redis 對象,對象頭中包含一個 24bit 的信息,作爲對象熱度的標誌。在 LRU 淘汰算法中,該標誌是一個時間戳,記錄了最近一次訪問該標誌位的時間。
在觸發了 LRU 淘汰時,Redis 會隨機抽取若干個(默認是 5 個)key,然後刪掉最舊的 key。如果這時候內存依舊超出限制,則再次抽選、刪除最舊的 Key 值,直到內存低於最大內存限制爲止。

Redis Object 的對象頭如下所示:

typedef struct redisObject {
    // 對象類型,如 zset, set, hash 等
    unsigned type: 4; 
    // 對象編碼如 ziplist, inset, skiplist 等
    unsigned encoding: 4;
    // 對象的熱度
    unsigned lru: 24;
    // 引用計數
    int refcount;
    // 對象的 body
    void *ptr;
}

其中,lru 值即爲表示熱度的值。在 LRU 模式下,該字段存儲的時間戳是 Redis 服務器的時鐘信息 server.lruclock,單位爲毫秒。server.lruclock 持續更新,某對象被訪問時,對象頭中的 LRU 值被更新爲當前 server.lruclock 的值,最後當觸發 LRU 內存淘汰時,該對象的 LRU 值會與當前 server.lruclock 進行取模等一系列運算,即可得到 LRU 值。

3.3 LFU 策略

LFU 策略與 LRU 的計算方式大致相同,都是根據 Redis 對象頭的 LRU 值與 server.lruclock 值進行計算的。但是 LFU 策略下,24bit 的 lru 值被分爲 16+8 兩部分。

  • ldt (last decrement time,): 前 16 位,記錄上一次更新時間,計算單位是分鐘。
    • ldt 不是對象被訪問的時候被更新,而是在 Redis 觸發淘汰邏輯時進行更新;
  • logc (logistic counter,對數計數): 後 8 位記錄頻率信息,且以對數形式儲存,計算單位是分鐘。
    • logc 有衰減算法,在 ldt 更新時觸發。當前 logc 值減去對象空閒時間,除以一個衰減係數;
    • 由於 logc 的統計的是對數信息,所以它的 +1 策略是基於概率的 +1;於是當對數值越大時,+1 操作概率越小,就越難被更新。大致流程如下:
      1. 計算差值:當前對數值 - 基值 (5)
      2. 計算更新 +1 操作概率:p = 1 / 差值
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章