一 Redis 內(nèi)存配置
Redis是基于內(nèi)存的key-value數(shù)據(jù)庫,因為系統(tǒng)的內(nèi)存大小有限咖楣,所以我們在使用Redis的時候可以配置Redis能使用的最大的內(nèi)存大小。
1.1 通過配置文件配置
通過在Redis安裝目錄下面的redis.conf配置文件中添加以下配置設(shè)置內(nèi)存大小
- redis的配置文件不一定使用的是安裝目錄下面的redis.conf文件,啟動redis服務(wù)的時候是可以傳一個參數(shù)指定redis的配置文件的
//設(shè)置Redis最大占用內(nèi)存大小為100M
maxmemory 100mb
1.2 通過命令修改
- Redis支持運行時通過命令動態(tài)修改內(nèi)存大小
//設(shè)置Redis最大占用內(nèi)存大小為100M
127.0.0.1:6379> config set maxmemory 100mb
- 獲取設(shè)置的Redis能使用的最大內(nèi)存大小
//獲取設(shè)置的Redis能使用的最大內(nèi)存大小
127.0.0.1:6379> config get maxmemory
- 如果不設(shè)置最大內(nèi)存大小或者設(shè)置最大內(nèi)存大小為0舶斧,在64位操作系統(tǒng)下不限制內(nèi)存大小强缘,在32位操作系統(tǒng)下最多使用3GB內(nèi)存
二 redis 過期策略
- redis 過期策略是:定期刪除+惰性刪除督惰。
定期刪除
所謂定期刪除,指的是 redis 默認(rèn)是每隔 100ms 就隨機(jī)抽取一些設(shè)置了過期時間的 key旅掂,檢查其是否過期赏胚,如果過期就刪除。
假設(shè) redis 里放了 10w 個 key商虐,都設(shè)置了過期時間觉阅,你每隔幾百毫秒,就檢查 10w 個 key秘车,那 redis 基本上就死了典勇,cpu 負(fù)載會很高的,消耗在你的檢查過期 key 上了叮趴。注意割笙,這里可不是每隔 100ms 就遍歷所有的設(shè)置過期時間的 key,那樣就是一場性能上的災(zāi)難眯亦。實際上 redis 是每隔 100ms 隨機(jī)抽取一些 key 來檢查和刪除的伤溉。
問題:
定期刪除可能會導(dǎo)致很多過期 key 到了時間并沒有被刪除掉,
解決:
使用惰性刪除妻率。
惰性刪除
在獲取某個 key 的時候乱顾,redis 會檢查一下 ,這個 key 如果設(shè)置了過期時間那么是否過期了宫静?如果過期了此時就會刪除走净,不會給你返回任何東西。
- 獲取 key 的時候孤里,如果此時 key 已經(jīng)過期温技,就刪除,不會返回任何東西扭粱。
問題:
如果定期刪除漏掉了很多過期 key舵鳞,然后你也沒及時去查,也就沒走惰性刪除琢蛤,此時會怎么樣蜓堕?如果大量過期 key 堆積在內(nèi)存里抛虏,導(dǎo)致 redis 內(nèi)存塊耗盡了,咋整套才?
答案是:走內(nèi)存淘汰機(jī)制迂猴。
三 Redis的內(nèi)存淘汰
Redis是基于內(nèi)存的緩存框架,所以配置內(nèi)存是受限于物理機(jī)內(nèi)存的大小背伴,當(dāng)內(nèi)容使用完之后沸毁,如果繼續(xù)往Redis中寫數(shù)據(jù)redis沒有內(nèi)存可用了會如何處理?會宕機(jī)嗎傻寂?
事實上息尺,宕機(jī)是不太可能的,Redis定義了幾種策略用來處理上述情況的放生:
- noeviction(默認(rèn)策略):不淘汰疾掰,對于寫請求不再提供服務(wù)搂誉,直接返回錯誤(DEL請求和部分特殊請求除外);
- allkeys-lru:從所有key中使用LRU算法進(jìn)行淘汰静檬;
- volatile-lru:從設(shè)置了過期時間的key中使用LRU算法進(jìn)行淘汰炭懊;
- allkeys-random:從所有key中隨機(jī)淘汰數(shù)據(jù);
- volatile-random:從設(shè)置了過期時間的key中隨機(jī)淘汰拂檩;
- volatile-ttl:在設(shè)置了過期時間的key中侮腹,根據(jù)key的過期時間進(jìn)行淘汰,越早過期的越優(yōu)先被淘汰稻励。
當(dāng)使用volatile-lru父阻、volatile-random、volatile-ttl這三種策略時钉迷,如果沒有key可以被淘汰,則和noeviction一樣返回錯誤钠署。
查詢Redis的內(nèi)存淘汰策略
127.0.0.1:6379> config get maxmemory-policy
配置Redis的內(nèi)存淘汰策略
- 通過配置文件設(shè)置淘汰策略(修改redis.conf文件):
maxmemory-policy allkeys-lru
- 通過命令修改淘汰策略:
127.0.0.1:6379> config set maxmemory-policy allkeys-lru
LRU
什么是LRU算法
LRU(Least Recently Used)糠聪,即最近最少使用,是一種緩存置換算法谐鼎。在使用內(nèi)存作為緩存的時候舰蟆,緩存的大小一般是固定的。當(dāng)緩存被占滿狸棍,這個時候繼續(xù)往緩存里面添加數(shù)據(jù)身害,就需要淘汰一部分老的數(shù)據(jù),釋放內(nèi)存空間用來存儲新的數(shù)據(jù)草戈。這個時候就可以使用LRU算法了塌鸯。其核心思想是:如果一個數(shù)據(jù)在最近一段時間沒有被用到,那么將來被使用到的可能性也很小唐片,所以就可以被淘汰掉丙猬。
LRU在Redis中的實現(xiàn)
1. 近似LRU算法
Redis使用的是近似LRU算法涨颜,它跟常規(guī)的LRU算法還不太一樣。近似LRU算法通過隨機(jī)采樣法淘汰數(shù)據(jù)茧球,每次隨機(jī)出5(默認(rèn))個key庭瑰,從里面淘汰掉最近最少使用的key。
- 可以通過maxmemory-samples參數(shù)修改采樣數(shù)量:例:maxmemory-samples 10 maxmenory-samples配置的越大抢埋,淘汰的結(jié)果越接近于嚴(yán)格的LRU算法弹灭。
Redis為了實現(xiàn)近似LRU算法,給每個key增加了一個額外增加了一個24bit的字段揪垄,用來存儲該key最后一次被訪問的時間穷吮。
2. Redis3.0對近似LRU的優(yōu)化
Redis3.0對近似LRU算法進(jìn)行了一些優(yōu)化。新算法會維護(hù)一個候選池(大小為16)福侈,池中的數(shù)據(jù)根據(jù)訪問時間進(jìn)行排序酒来,第一次隨機(jī)選取的key都會放入池中,隨后每次隨機(jī)選取的key只有在訪問時間小于池中最小的時間才會放入池中肪凛,直到候選池被放滿堰汉。當(dāng)放滿后,如果有新的key需要放入伟墙,則將池中最后訪問時間最大(最近被訪問)的移除翘鸭。
當(dāng)內(nèi)存不足需要淘汰的時候,則直接從池中選取最近訪問時間最写量(最久沒被訪問)的key淘汰掉就行就乓。
3. ##### LRU算法的對比
通過一個實驗對比各LRU算法的準(zhǔn)確率,先往Redis里面添加一定數(shù)量的數(shù)據(jù)n拱烁,使Redis可用內(nèi)存用完生蚁,再往Redis里面添加n/2的新數(shù)據(jù),這個時候就需要淘汰掉一部分的數(shù)據(jù)戏自,如果按照嚴(yán)格的LRU算法邦投,應(yīng)該淘汰掉的是最先加入的n/2的數(shù)據(jù)。生成如下各LRU算法的對比圖
- 淺灰色是被淘汰的數(shù)據(jù)
- 灰色是沒有被淘汰掉的老數(shù)據(jù)
- 綠色是新加入的數(shù)據(jù)
能看到Redis3.0采樣數(shù)是10生成的圖最接近于嚴(yán)格的LRU擅笔。而同樣使用5個采樣數(shù)志衣,Redis3.0也要優(yōu)于Redis2.8。
LFU算法
什么是LFU算法
LFU算法是Redis4.0里面新加的一種淘汰策略猛们。它的全稱是Least Frequently Used念脯,它的核心思想是根據(jù)key的最近被訪問的頻率進(jìn)行淘汰,很少被訪問的優(yōu)先被淘汰弯淘,被訪問的多的則被留下來绿店。
LFU算法能更好的表示一個key被訪問的熱度。假如你使用的是LRU算法庐橙,一個key很久沒有被訪問到惯吕,只剛剛是偶爾被訪問了一次惕它,那么它就被認(rèn)為是熱點數(shù)據(jù),不會被淘汰废登,而有些key將來是很有可能被訪問到的則被淘汰了淹魄。如果使用LFU算法則不會出現(xiàn)這種情況,因為使用一次并不會使一個key成為熱點數(shù)據(jù)堡距。
LFU一共有兩種策略:
- volatile-lfu:在設(shè)置了過期時間的key中使用LFU算法淘汰key甲锡;
- allkeys-lfu:在所有的key中使用LFU算法淘汰數(shù)據(jù)
設(shè)置使用這兩種淘汰策略跟前面講的一樣,不過要注意的一點是這兩周策略只能在Redis4.0及以上設(shè)置羽戒,如果在Redis4.0以下設(shè)置會報錯缤沦。