1. 程式人生 > 其它 >redis--LRU驅動事件(LRU eviction)

redis--LRU驅動事件(LRU eviction)

  LRU是Redis支援的回收方法。本頁面包括一些常規話題,Redis的maxmemory指令用於將可用記憶體限制成一個固定大小,還包括了Redis使用的LRU演算法,這個實際上只是近似的LRU。

Maxmemory配置指令

maxmemory配置指令用於配置Redis儲存資料時指定限制的記憶體大小。通過redis.conf可以設定該指令,或者之後使用CONFIG SET命令來進行執行時配置。

例如為了配置記憶體限制為100mb,以下的指令可以放在redis.conf檔案中。

maxmemory 100mb

設定maxmemory為0代表沒有記憶體限制。對於64位的系統這是個預設值,對於32位的系統預設記憶體限制為3GB。

當指定的記憶體限制大小達到時,需要選擇不同的行為,也就是策略。 Redis可以僅僅對命令返回錯誤,這將使得記憶體被使用得更多,或者回收一些舊的資料來使得新增資料時可以避免記憶體限制。

回收策略

當maxmemory限制達到的時候Redis會使用的行為由 Redis的maxmemory-policy配置指令來進行配置。

以下的策略是可用的:

  • noeviction:返回錯誤當記憶體限制達到並且客戶端嘗試執行會讓更多記憶體被使用的命令(大部分的寫入指令,但DEL和幾個例外)
  • allkeys-lru: 嘗試回收最少使用的鍵(LRU),使得新新增的資料有空間存放。
  • volatile-lru: 嘗試回收最少使用的鍵(LRU),但僅限於在過期集合的鍵,使得新新增的資料有空間存放。
  • allkeys-random: 回收隨機的鍵使得新新增的資料有空間存放。
  • volatile-random: 回收隨機的鍵使得新新增的資料有空間存放,但僅限於在過期集合的鍵。
  • volatile-ttl: 回收在過期集合的鍵,並且優先回收存活時間(TTL)較短的鍵,使得新新增的資料有空間存放。

如果沒有鍵滿足回收的前提條件的話,策略volatile-lruvolatile-random以及volatile-ttl就和noeviction 差不多了。

選擇正確的回收策略是非常重要的,這取決於你的應用的訪問模式,不過你可以在執行時進行相關的策略調整,並且監控快取命中率和沒命中的次數,通過RedisINFO命令輸出以便調優。

一般的經驗規則:

  • 使用allkeys-lru策略:當你希望你的請求符合一個冪定律分佈,也就是說,你希望部分的子集元素將比其它其它元素被訪問的更多。如果你不確定選擇什麼,這是個很好的選擇。.
  • 使用allkeys-random:如果你是迴圈訪問,所有的鍵被連續的掃描,或者你希望請求分佈正常(所有元素被訪問的概率都差不多)。
  • 使用volatile-ttl:如果你想要通過建立快取物件時設定TTL值,來決定哪些物件應該被過期。

allkeys-lru 和 volatile-random策略對於當你想要單一的例項實現快取及持久化一些鍵時很有用。不過一般執行兩個例項是解決這個問題的更好方法。

為了鍵設定過期時間也是需要消耗記憶體的,所以使用allkeys-lru這種策略更加高效,因為沒有必要為鍵取設定過期時間當記憶體有壓力時。

回收程序如何工作

理解回收程序如何工作是非常重要的:

  • 一個客戶端運行了新的命令,添加了新的資料。
  • Redi檢查記憶體使用情況,如果大於maxmemory的限制, 則根據設定好的策略進行回收。
  • 一個新的命令被執行,等等。
  • 所以我們不斷地穿越記憶體限制的邊界,通過不斷達到邊界然後不斷地回收回到邊界以下。

如果一個命令的結果導致大量記憶體被使用(例如很大的集合的交集儲存到一個新的鍵),不用多久記憶體限制就會被這個記憶體使用量超越。

近似LRU演算法

Redis的LRU演算法並非完整的實現。這意味著Redis並沒辦法選擇最佳候選來進行回收,也就是最久未被訪問的鍵。相反它會嘗試執行一個近似LRU的演算法,通過對少量keys進行取樣,然後回收其中一個最好的key(被訪問時間較早的)。

不過從Redis 3.0演算法已經改進為回收鍵的候選池子。這改善了演算法的效能,使得更加近似真是的LRU演算法的行為。

Redis LRU有個很重要的點,你通過調整每次回收時檢查的取樣數量,以實現調整演算法的精度。這個引數可以通過以下的配置指令調整:

maxmemory-samples 5

Redis為什麼不使用真實的LRU實現是因為這需要太多的記憶體。不過近似的LRU演算法對於應用而言應該是等價的。使用真實的LRU演算法與近似的演算法可以通過下面的影象對比。

用於生成影象的Redis服務被填充了指定數量的鍵。這些鍵將被從頭到尾訪問,所以當使用LRU演算法時第一個鍵是最佳的回收候選鍵。接著新增超過50%的鍵,用於強制舊鍵被回收。

你可以看到三種點在圖片中, 形成了三種帶.

  • 淺灰色帶是已經被回收的物件。
  • 灰色帶是沒有被回收的物件。
  • 綠色帶是被新增的物件。
  • 在LRU實現的理論中,我們希望的是,在舊鍵中的第一半將會過期。Redis的LRU演算法則是概率的過期舊的鍵。

你可以看到,在都是五個取樣的時候Redis 3.0比Redis 2.8要好,Redis2.8中在最後一次訪問之間的大多數的物件依然保留著。使用10個取樣大小的Redis 3.0的近似值已經非常接近理論的效能。

注意LRU只是個預測鍵將如何被訪問的模型。另外,如果你的資料訪問模式非常接近冪定律,大部分的訪問將集中在一個鍵的集合中,LRU的近似演算法將處理得很好。

在模擬實驗的過程中,我們發現如果使用冪定律的訪問模式,則真實的LRU演算法和近似的Redis演算法幾乎沒有差別。

當然你可以提升取樣大小到10,消耗更多的CPU時間以實現更真實的LRU演算法,同時檢視下是否讓你的快取命中率有差別。

通過CONFIG SET maxmemory-samples 命令在生產環境上設定不同的取樣大小是非常簡單的。