Redis 緩存逐出策略

  • 把 Redis 當作緩存使用時,有時你能夠方便的讓它在新數據時自動逐出舊數據。這一點你們都比較清楚,由於 memcached 默認也會這麼幹redis

  • Redis 僅支持 LRU 逐出策略。下文主要講述 Redis maxmemory 指令,這個指令用於限定內存使用量,以及講述了 Redis 使用到的 LRU 算法,這是一種近似LRU算法。算法

  • maxmemory 配置指令緩存

    • maxmemory 指令用於限定內存使用量。能夠在 redis.conf 文件中設置,也能夠經過 CONFIG SET 命令在運行時設置。dom

    • 例如在 redis.conf 文件中添加以下指令將內存限定在 100M 之內memcached

      • maxmemory 100mb性能

    • 設置成 0 時表示無限制。64位系統下默認無限制,32位系統則強制指定爲 3GBspa

    • 當內存使用達到限定值時,能夠選擇幾種不一樣的策略。例如 Redis 能夠在調用指令時直接返回錯誤(這些指令會致使更多內存使用),或者是逐出老數據,給新數據納出空間,讓內存佔用保持在限定一下。對象

  • 逐出策略ip

    • 具體的逐出策略經過 maxmemory-policy 指令進行配置,主要有以下策略:內存

      • noeviction:調用某些指令時返回錯誤(主要是絕大多數的寫指令,DEL 和 部分其餘指令不包括)

      • allkeys-lru:對全鍵進行LRU

      • volatile-lru:對指定了過時時間(expire set)的鍵進行LRU

      • allkeys-random:對全鍵進行隨機逐出

      • volatile-random:對指定了過時時間的鍵隨機逐出

      • volatile-ttl:對指定了過時時間,而且 TTL 較短的鍵進行逐出

    • volatile-* 系列指令在無鍵值知足條件時(例如未設置過時時間),表現爲 noeviction

    • 不一樣的應用選擇不一樣的逐出策略,固然你能夠根據命中率(INFO指令)在運行時動態調整策略。

    • 能夠參考如下的經驗法則:

      • allkeys-lru,預期的請求符合長尾理論。或是啥都不懂時配成這個不會太差

      • allkeys-random,會持續輪詢全部的鍵。或者預期的請求符合均勻分佈

      • volatile-ttl,在生成緩存對象時指定不一樣的 ttl 值,因此你得控制好

    • 你在單實例上同時存儲緩存數據,以及一些持久化數據時,volatile-lru 和 volatile-random 會比較適合。可是一般建議緩存數據和持久化數據用不一樣的實例存儲。

    • 另外,對一個鍵設置過時時間會佔用額外的內存,因此在內存壓力較大時 allkeys-lru 的內存使用率會較好。

  • 逐出過程是如何實現的

    • 最好從如下幾個方面來了解逐出過程

      • 客戶端運行了一個消耗內存的指令

      • Redis 檢查內存佔用後發現超限,執行逐出策略

      • 執行一個新的指令,如此循環

    • 即反覆的讓 Redis 的內存佔用在限定值上下波動,來觀察和驗證逐出策略

    • 當一個指令消耗較多內存時,必定時間範圍內能夠觀察到明顯的內存超限

  • 近似LRU算法

    • Redis 使用的 LRU 算法是一個近似實現,即逐出Key並不必定真正訪問最少的鍵。它採用的方式是,對逐出範圍內的鍵進行採樣,而後對樣本進行逐出。什麼鬼。

    • 在 Redis 3.0中有了一些改進,在提高性能的同時,讓近似LRU的結果更加接近真實LRU。

    • Redis LRU挺重要的一點是,你能夠調整算法精度,即調整每次逐出時的取樣數。能夠經過這個指令進行調整:

      • maxmemory-samples 5

    • Redis 使用 近似LRU 的目的主要仍是爲了節省內存,對於應用來講,近似與真實,其實是等效的。

    clipboard.png

  • 在 Redis 中填充滿指定數目的數據,順序訪問全部的鍵,在LRU下,第一個鍵是最佳逐出對象。而後增長50%的鍵值,逐出一半的老數據。

  • 圖中的三種點造成了三條不一樣的條紋

    • 淺灰色表示已經逐出的

    • 灰色表示未被逐出的

    • 綠色表示新增的

  • 理論LRU的結果徹底符合預期,前一半的老數據逐出。Redis LRU 則是機率上的逐出老數據。

  • 能夠看到,取樣數爲5時,Redis 3.0 比 Redis 2.8 效果要好不少,2.8逐出了很多剛剛被訪問過的數據。取樣數爲10時,Redis 3.0 的表現跟理論LRU就很是接近了。

  • 若是請求符合長尾法則,那麼真實LRU與Redis LRU之間表現基本無差別。

  • 你能夠在增長必定CPU消耗的狀況下,提升取樣數,而後檢查命中率是否有變化

  • 在生產環境,經過 CONFIG SET maxmemory-samples <count> 指令能夠方便的設置取樣數。

相關文章
相關標籤/搜索