[TOC]
1. Redis 被當(dāng)做緩存使用
當(dāng)Redis被當(dāng)做緩存來使用,當(dāng)你新增數(shù)據(jù)時妒蛇,讓它自動地回收舊數(shù)據(jù)是件很方便的事情机断。這個行為在開發(fā)者社區(qū)非常有名楷拳,因為它是流行的memcached系統(tǒng)的默認(rèn)行為绣夺。
LRU是Redis唯一支持的回收方法。
2. LRU算法
LRU是Least Recently Used的縮寫欢揖,即最近最少使用陶耍,是一種常用的頁面置換算法,選擇最近最久未使用的頁面予以淘汰她混。該算法賦予每個頁面一個訪問字段烈钞,用來記錄一個頁面自上次被訪問以來所經(jīng)歷的時間 t,當(dāng)須淘汰一個頁面時坤按,選擇現(xiàn)有頁面中其 t 值最大的毯欣,即最近最少使用的頁面予以淘汰。
----百度百科
主存容量遠(yuǎn)大于CPU緩存臭脓,磁盤容量遠(yuǎn)大于主存酗钞,因此無論是哪一層次的緩存都面臨一個同樣的問題:當(dāng)容量有限的緩存的空閑空間全部用完后,又有新的內(nèi)容需要添加進緩存時,如何挑選并舍棄原有的部分內(nèi)容砚作,從而騰出空間放入這些新的內(nèi)容窘奏。解決這個問題的算法有幾種,如最久未使用算法(LFU)葫录、先進先出算法(FIFO)着裹、最近最少使用算法(LRU)、非最近使用算法(NMRU)等米同,這些算法在不同層次的緩存上執(zhí)行時擁有不同的效率和代價骇扇,需根據(jù)具體場合選擇最合適的一種。
----維基百科
通俗理解就是哪個緩存最近被使用的最少面粮,就應(yīng)該丟棄匠题。
2.1 LRU算法
LRU(Least recently used,最近最少使用)算法根據(jù)數(shù)據(jù)的歷史訪問記錄來進行淘汰數(shù)據(jù)但金,其核心思想是“如果數(shù)據(jù)最近被訪問過韭山,那么將來被訪問的幾率也更高”。
一個緩存隊列冷溃。
-
原理:
- 新數(shù)據(jù)放到隊列頭
- 每當(dāng)緩存被命中钱磅,將緩存移動到隊列頭
- 丟棄數(shù)據(jù)總是從隊列尾部開始
-
命中率:
當(dāng)存在批量的操作時,容易造成LRU命中率下降似枕,造成存儲污染盖淡。
比如一直都是訪問1,2,3.如果有一個后臺任務(wù),將4,5,6掃描了一次凿歼,此時褪迟,如果需要丟棄,就會將熱點緩存丟棄答憔。造成緩存污染味赃。
復(fù)雜度:簡單
消耗:較高,命中需要遍歷隊列虐拓,命中需要做元素的轉(zhuǎn)移心俗。
2.2 LRU-K算法
在2.1中的LRU算法是,每當(dāng)緩存被命中蓉驹,就移動到頭部城榛。而LRU-K是指,當(dāng)緩存被命中K次時态兴,才會做元素的轉(zhuǎn)移狠持。
其核心思想是,命中一次可能不太可靠瞻润,需要命中指定的次數(shù)喘垂,才能被認(rèn)為是熱點緩存献汗。
相比LRU算法,LRU-K需要額外維護一個隊列==歷史訪問隊列==王污。
一個緩存隊列罢吃,一個緩存訪問歷史隊列。
-
原理:
- 緩存數(shù)據(jù)第一次被命中昭齐,將命中次數(shù)++
- 當(dāng)命中次數(shù)達(dá)到K尿招,將緩存數(shù)據(jù)轉(zhuǎn)移到緩存隊列
- 丟棄數(shù)據(jù)總是從緩存隊列的尾部開始
img 命中率:因為LRU-K算法能在一定程度上去除突發(fā)或者批量操作的干擾,所以命中率比LRU算法要高阱驾。
復(fù)雜度:多維護一個隊列就谜,需要額外的成本。
消耗:LRU-K可以選擇即時轉(zhuǎn)移元素里覆,或者丟棄時轉(zhuǎn)移丧荐,在轉(zhuǎn)移的時候,有內(nèi)存消耗喧枷。
2.3 LRU-Two queues
LRU-Two queues類似LRU-2.區(qū)別在于將緩存訪問歷史隊列(不是緩存數(shù)據(jù)隊列)換成FIFO緩存隊列虹统。
所以LRU-T算法中,有兩個緩存隊列:FIFO緩存隊列和LRU緩存隊列隧甚。
緩存數(shù)據(jù)第一次被命中時车荔,放入FIFO緩存隊列;如果緩存數(shù)據(jù)第二次被命中戚扳,放入LRU緩存隊列忧便。
這兩個緩存隊列各自按照自己的緩存數(shù)據(jù)淘汰策略進行替換緩存。
- 原理:
- 新訪問數(shù)據(jù)放入FIFO緩存隊列
- FIFO中的緩存數(shù)據(jù)被再次命中帽借,那么轉(zhuǎn)移到LRU緩存隊列中
- 如果LRU緩存隊列中的緩存數(shù)據(jù)被命中珠增,那么就將緩存數(shù)據(jù)轉(zhuǎn)移到LRU隊列頭部
- 丟棄數(shù)據(jù)從LRU或者FIFO隊列的尾部開始
- 命中率:LRU-T算法的命中率高于LRU算法,在一定程度上也高于LRU-K算法砍艾。
- 復(fù)雜度:兩個隊列蒂教,不過每個單個隊列都比較簡單
- 消耗:FIFO和LRU消耗總和
2.4 Multi Queue
Multi Queue算法根據(jù)訪問頻率將數(shù)據(jù)劃分為多個隊列,不同的隊列具有不同的訪問優(yōu)先級辐董,其核心思想是:優(yōu)先緩存訪問次數(shù)多的數(shù)據(jù)悴品。
Multi Queue算法將緩存劃分為多個LRU隊列禀综,每個隊列對應(yīng)不同的訪問優(yōu)先級简烘。訪問優(yōu)先級是根據(jù)訪問次數(shù)計算出來的。
- 原理:
- 新緩存數(shù)據(jù)在最低優(yōu)先級的隊列定枷,每個隊列按照LRU隊列管理
- 緩存命中次數(shù)達(dá)到一定的閾值孤澎,提升優(yōu)先級,進行隊列轉(zhuǎn)移
- 防止高優(yōu)先級累積效應(yīng)欠窒,在一定時間內(nèi)覆旭,高優(yōu)先級的緩存數(shù)據(jù)沒有被命中退子,需要做降級
- 緩存數(shù)據(jù)丟棄存在丟棄臨時隊列
- 丟棄數(shù)據(jù)從丟棄臨時隊列開始
- 命中率:Multi Queue降低了“緩存污染”帶來的問題,命中率比LRU要高型将。
- 復(fù)雜度:Multi Queue需要維護多個隊列寂祥,且需要維護每個數(shù)據(jù)的訪問時間,復(fù)雜度比LRU高七兜。
- 消耗:Multi Queue需要記錄每個數(shù)據(jù)的訪問時間丸凭,需要定時掃描所有隊列,時間消耗比LRU要高腕铸∠空間上因為每個優(yōu)先級隊列的長度都很小,所以狠裹,空間消耗差不多虽界。
3. Maxmemory配置
maxmemory size
用于配置Redis存儲數(shù)據(jù)時,指定限制的內(nèi)存大小涛菠。==此配置放在redis.conf中即可莉御。==
也可以使用CONFIG SET
來運行時配置。
CONFIG SET
命令用于在服務(wù)器運行期間重寫某些配置俗冻,而不用重啟Redis颈将。你可以使用此命令更改不重要的參數(shù)或從一個參數(shù)切換到另一個持久性選項。
可以通過CONFIG GET *
獲得CONFIG SET
命令支持的配置參數(shù)列表言疗,該命令是用于獲取有關(guān)正在運行的Redis實例的配置信息的對稱命令晴圾。
所有使用CONFIG SET
設(shè)置的配置參數(shù)將會立即被Redis加載,并從下一個執(zhí)行的命令開始生效噪奄。
設(shè)置maxmemory 0
表示無內(nèi)存大小限制死姚,可以使用所有的內(nèi)存容量。
對于32位操作系統(tǒng)勤篮,默認(rèn)內(nèi)存限制3GB都毒。對于64位操作系統(tǒng),默認(rèn)內(nèi)存無限制碰缔。
4. 內(nèi)存回收策略
當(dāng)指定的內(nèi)存限制大小達(dá)到時账劲,需要選擇不同的行為,也就是策略金抡。
redis可以僅僅對命令返回錯誤瀑焦,這將導(dǎo)致內(nèi)存被使用的更多」8危或者回收一些舊的數(shù)據(jù)來使得添加數(shù)據(jù)時避免內(nèi)存限制榛瓮。
當(dāng)maxmemory
限制達(dá)到的時候,redis使用的策略由maxmemory-policy
配置指定巫击。
maxmemory-policy
有以下待選:
- noeviction: 返回錯誤禀晓。當(dāng)內(nèi)存限制達(dá)到精续,并且客戶端嘗試執(zhí)行更多內(nèi)存被使用的命令(一些刪除或者可能導(dǎo)致內(nèi)存占用減少的命令除外)
- allkeys-lru:使用LRU算法。最少使用的緩存數(shù)據(jù)將被丟棄粹懒。
- volatile-lru:類似使用LRU-K算法重付。擁有兩個隊列,一個是緩存隊列凫乖,一個是過期隊列堪夭,丟棄數(shù)據(jù)從過期隊列開始。
- allkeys-random:隨機回收緩存數(shù)據(jù)拣凹。
- volatile-random:隨機回收過期隊列的緩存數(shù)據(jù)森爽。
- volatile-ttl:回收過期隊列的緩存數(shù)據(jù),而且優(yōu)先回收存活時間(ttl)較短的緩存數(shù)據(jù)嚣镜。
對于volatile前綴的策略爬迟,如果回收條件不滿足的話,那么和noeviction相同菊匿。
選擇正確的回收策略非常重要付呕,但是往往很多時候,策略的選擇需要大量的經(jīng)驗跌捆。
所以一開始可以根據(jù)這些特點選擇:
- allkey-lru:請求符合冪定理分布徽职。即子集數(shù)據(jù)比其他數(shù)據(jù)訪問頻次更多∨搴瘢或者數(shù)據(jù)存在較為明顯的熱點分布的時候姆钉。
- allkey-random:請求均勻分布,每個數(shù)據(jù)被訪問的頻次差不多抄瓦,沒有明顯區(qū)別潮瓶。
- volatitle-ttl:數(shù)據(jù)有過期時間,或者大部分有過期時間钙姊。
過期時間的設(shè)置與維護毯辅,也是一個耗費資源的過程,所以使用allkeys-lru可能是更加高效的選擇煞额。
在配置了內(nèi)存回收策略后思恐,可以使用INFO
命令查看瞬時redis服務(wù)器的資源消耗情況。
然后在分析redis資源使用情況膊毁,進行調(diào)整內(nèi)存回收策略胀莹。
5. 回收原理
原理:
- 客戶端執(zhí)行了新的命令,增加了新的數(shù)據(jù)媚媒,一塊內(nèi)存被占用
- redis在命令執(zhí)行完后嗜逻,檢查內(nèi)存使用情況,如果內(nèi)存限制超出
maxmemory
限制缭召,那么調(diào)用maxmemory-policy
的策略進行回收
所以栈顷,設(shè)置了maxmemory
并不是強制的,redis可能在很短的時間內(nèi)嵌巷,內(nèi)存占用超出了maxmemory
的限制萄凤。redis的內(nèi)存占用不斷的穿越邊界值maxmemory
,不斷的達(dá)到并超過邊界搪哪,然后又不斷的回收回到邊界以下靡努。
6. redis的LRU算法
redis的LRU算法,并不是標(biāo)準(zhǔn)的LRU算法晓折。
標(biāo)準(zhǔn)的LRU算法惑朦,需要將全部的緩存數(shù)據(jù)放到隊列中,這樣會消耗較多的內(nèi)存漓概。特別是對于redis經(jīng)常緩存億萬的數(shù)據(jù)來說漾月,將全部的key或者緩存數(shù)據(jù)放到隊列中,這幾乎是無法想象的災(zāi)難胃珍。
所以梁肿,在redis中使用標(biāo)準(zhǔn)的LRU算法是一種性能非常差的選擇,因此觅彰,在redis中使用的是近似的LRU算法吩蔑。
redis中近似的LRU算法與標(biāo)準(zhǔn)的LRU算法的區(qū)別在于:標(biāo)準(zhǔn)的LRU算法會將全部的數(shù)據(jù)進行統(tǒng)計;而redis近似的LRU算法則是隨機采樣填抬,隨機采樣指定個數(shù)的緩存數(shù)據(jù)烛芬,然后根據(jù)采樣結(jié)果,確定丟棄的緩存數(shù)據(jù)飒责。
==請注意蛀骇,這里的丟棄只是從內(nèi)存中丟棄,數(shù)據(jù)不會丟失读拆。類似我們硬盤上有16個G的數(shù)據(jù)擅憔,但是只有2G的內(nèi)存,那么需要計算機不斷的將新的數(shù)據(jù)從硬盤讀取檐晕,覆蓋舊的內(nèi)存數(shù)據(jù)暑诸。==
在redis.conf中有一個配置redis的LRU算法采樣數(shù)量的配置maxmemory-samples num
,采樣數(shù)值越大,采樣范圍越大辟灰,得出的結(jié)論越準(zhǔn)確个榕。如果采樣是全體數(shù)據(jù),那么準(zhǔn)確率就是100%芥喇。不過采樣范圍的擴大西采,會導(dǎo)致整個采樣過程,需要消耗更多的資源继控。
maxmemory-samples
也可以使用config set進行設(shè)置械馆。
這是redis官網(wǎng)的采樣測試結(jié)果:
[圖片上傳失敗...(image-16994-1596192689711)]
上面的圖片可以被分為4個小塊:第一個左上是標(biāo)準(zhǔn)LRU算法胖眷,第二個右上是采樣10次的redis近似LRU算法,第三個左下是采樣5次的結(jié)果,redis2.8霹崎,第四個右下是采樣5次的結(jié)果珊搀,redis3.0.
小圖是從上到下,從左到右創(chuàng)建尾菇,也就是左上角的小點是第一個境析,右下是最后一個。有時間順序派诬。
每一個小圖中劳淆,有三種顏色的小點組成:
- 淺灰色:數(shù)據(jù)被回收
- 深灰色:數(shù)據(jù)沒有被回收
- 深綠色:數(shù)據(jù)新建
當(dāng)采樣次數(shù)為5時苞轿,redis3.0好于redis2.8.在第三個中端仰,存在大量的深灰色小點,而且分布沒有明顯的界限小渊,即使很多很早時間創(chuàng)建放可,也沒有被回收谒臼。
在第四個圖找那個,我們可以明顯的看到灰色區(qū)域有較為明顯的分割帶耀里,不過深灰色色帶所占比例不是很多蜈缤,還不是非常理想。
對于都redis3.0比較冯挎,第二個灰色之間有更加明顯的分隔帶底哥,而且色帶分布比例均勻,差不多是50%.
與標(biāo)準(zhǔn)的LRU算法結(jié)果比較房官,采樣次數(shù)高趾徽,redis版本新,算法更接近標(biāo)準(zhǔn)LRU翰守。