當(dāng)Redis作為緩存使用時,,當(dāng)你添加新的數(shù)據(jù)時,,有時候很方便使Redis自動回收老的數(shù)據(jù)。這種行為在開發(fā)者社區(qū)中眾所周知,,因?yàn)檫@是流行的memcached 系統(tǒng)的默認(rèn)行為,。
LRU實(shí)際上是被唯一支持的數(shù)據(jù)移除方法。本文內(nèi)容將包含Redis的maxmemory指令,,用于限制內(nèi)存使用到一個固定的容量,,也包含深入探討Redis使用的LRU算法,一個近似準(zhǔn)確的LRU,。 maxmemory配置指令(configuration directive) maxmemory配置指令是用來配置Redis為數(shù)據(jù)集使用指定的內(nèi)存容量大小,。可以使用redis.conf文件來設(shè)置配置指令,,或者之后在運(yùn)行時使用CONFIG SET命令,。 例如,為了配置內(nèi)存限制為100MB,,可以在redis.conf文件中使用以下指令 Java代碼
設(shè)置maxmemory為0,,表示沒有內(nèi)存限制。這是64位系統(tǒng)的默認(rèn)行為,,32位的系統(tǒng)則使用3G大小作為隱式的內(nèi)存限制,。 當(dāng)指定的內(nèi)存容量到達(dá)時,,需要選擇不同的行為,即策略,。Redis可以只為命令返回錯誤,,這樣將占用更多的內(nèi)存,或者每次添加新數(shù)據(jù)時,,回收掉一些舊的數(shù)據(jù)以避免內(nèi)存限制,。 回收策略(Eviction policies) 當(dāng)maxmemory限制到達(dá)的時候,Redis將采取的準(zhǔn)確行為是由maxmemory-policy配置指令配置的,。 以下策略可用:
當(dāng)沒有滿足前提條件的話,volatile-lru,,volatile-random和volatile-ttl策略就表現(xiàn)得和noeviction一樣了,。 選擇正確的回收策略是很重要的,取決于你的應(yīng)用程序的訪問模式,,但是,,你可以在程序運(yùn)行時重新配置策略,使用INFO輸出來監(jiān)控緩存命中和錯過的次數(shù),,以調(diào)優(yōu)你的設(shè)置,。 一般經(jīng)驗(yàn)規(guī)則:
當(dāng)你想使用單個實(shí)例來實(shí)現(xiàn)緩存和持久化一些鍵,,allkeys-lru和volatile-random策略會很有用,。但是,通常最好是運(yùn)行兩個Redis實(shí)例來解決這個問題,。 另外值得注意的是,,為鍵設(shè)置過期時間需要消耗內(nèi)存,所以使用像allkeys-lru這樣的策略會更高效,,因?yàn)樵趦?nèi)存壓力下沒有必要為鍵的回收設(shè)置過期時間,。 回收過程(Eviction process) 理解回收的過程是這么運(yùn)作的非常的重要:
我們通過檢查,,然后回收鍵以返回到限制以下,,來連續(xù)不斷的穿越內(nèi)存限制的邊界。 如果一個命令導(dǎo)致大量的內(nèi)存被占用(像一個很大的集合交集保存到一個新的鍵),,一會功夫內(nèi)存限制就會被這個明顯的內(nèi)存量所超越,。 近似的LRU算法(Approximated LRU algorithm) Redis的LRU算法不是一個精確的實(shí)現(xiàn)。這意味著Redis不能選擇最佳候選鍵來回收,,也就是最久錢被訪問的那些鍵,。相反,會嘗試運(yùn)營一個近似的LRU算法,,通過采樣一小部分鍵,,然后在采樣鍵中回收最適合(擁有最久訪問時間)的那個。 然而,,從Redis3.0(當(dāng)前還是beta版本)開始,,算法被改進(jìn)為持有回收候選鍵的一個池子。這改善了算法的性能,,使得更接近于真實(shí)的LRU算法的行為 Redis的LRU算法有一點(diǎn)很重要,,你可以調(diào)整算法的精度,,通過改變每次回收時檢查的采樣數(shù)量。這個參數(shù)可以通過如下配置指令: Java代碼
Redis沒有使用真實(shí)的LRU實(shí)現(xiàn)的原因,,是因?yàn)檫@會消耗更多的內(nèi)存,。然而,近似值對使用Redis的應(yīng)用來說基本上也是等價(jià)的,。下面的圖形對比,,為Redis使用的LRU近似值和真實(shí)LRU之間的比較。 用于測試生成上面圖像的Redis服務(wù)被填充了指定數(shù)量的鍵,。鍵被從頭訪問到尾,,所以第一個鍵是LRU算法的最佳候選回收鍵。然后,,再新添加50%的鍵,,強(qiáng)制一般的舊鍵被回收。 你可以從圖中看到三種不同的原點(diǎn),,形成三個不同的帶,。
在理論的LRU實(shí)現(xiàn)中,我們期待看到的是,,在舊鍵中第一半會過期,。而Redis的LRU算法則只是概率性的過期這些舊鍵。 你可以看到,,同樣采用5個采樣,,Redis 3.0表現(xiàn)得比Redis 2.8要好,Redis 2.8中最近被訪問的對象之間的對象仍然被保留,。在Redis 3.0中使用10為采樣大小,,近似值已經(jīng)非常接近理論性能。 注意,,LRU只是一個預(yù)言指定鍵在未來如何被訪問的模式,。另外,如果你的數(shù)據(jù)訪問模式非常接近冪律,,大多數(shù)的訪問都將集中在一個集合中,,LRU近似算法將能處理得很好。 在模擬實(shí)驗(yàn)的過程中,,我們發(fā)現(xiàn)使用冪律訪問模式,,真實(shí)的LRU算法和Redis的近似算法之間的差異非常小,或者根本就沒有,。 然而,,你可以提高采樣大小到10,這會消耗額外的CPU,來更加近似于真實(shí)的LRU算法,,看看這會不會使你的緩存錯失率有差異,。 使用CONFIG SET maxmemory-samples <count>命令在生產(chǎn)環(huán)境上試驗(yàn)各種不同的采樣大小值是很簡單的。 |
|