将redis当做使用LRU算法的缓存来使用
當Redis被當做緩存來使用,當你新增數據時,讓它自動地回收舊數據是件很方便的事情。這個行為在開發者社區非常有名,因為它是流行的memcached系統的默認行為。
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-lru,?volatile-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 5Redis為什么不使用真實的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?命令在生產環境上設置不同的采樣大小是非常簡單的。
原文:http://www.redis.cn/topics/lru-cache.html
總結
以上是生活随笔為你收集整理的将redis当做使用LRU算法的缓存来使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 笔试题:写一个ArrayList 的动态
- 下一篇: Redis命令:EXPIREAT key