Redis緩存過期淘汰策略用法解讀
先來看下我們遇到的問題
- 生產(chǎn)上redis內(nèi)存需要設(shè)置多少才合適
- 如何配置、修改redis的內(nèi)存大小,具體怎么操作
- 如果內(nèi)存滿了Redis怎么辦
- redis清理內(nèi)存的方式選擇那種:定期刪除和惰性刪
- 怎么選擇redis緩存淘汰策略
1.redis內(nèi)存
1.1 查看Redis內(nèi)存
- 配置文件查看Redis最大占用內(nèi)存
maxmemory <bytes>
打開redis配置文件,設(shè)置maxmemory參數(shù),maxmemory是bytes字節(jié)類型,注意類型轉(zhuǎn)換
- 通過命令查看默認(rèn)的內(nèi)存大小
127.0.0.1:6379>config get maxmemory
默認(rèn)內(nèi)存大小為0嗎?那我們之前的數(shù)據(jù)是怎么保存進(jìn)去的?
1.2 redis默認(rèn)內(nèi)存
如果不設(shè)置最大內(nèi)存或者設(shè)置最大內(nèi)存大小為0,在64位操作系統(tǒng)下不限制內(nèi)存大小,在32位操作系統(tǒng)下最多使用3GB內(nèi)存
注意:在64bit系統(tǒng)下,maxmemory設(shè)置為0表示不限制redis內(nèi)存使用
一般生產(chǎn)上你如何配置
一般推薦Redis設(shè)置內(nèi)存為最大物理內(nèi)存的3/4
1.3 修改redis內(nèi)存設(shè)置
- 通過修改文件配置
maxmemory 1056236
- 通過命令修改,但是redis重啟后會失效
127.0.0.1:6379>config set maxmemory 104856986
查看redis內(nèi)存使用命令
127.0.0.1:6379>info memory 127.0.0.1:6379>config get maxmemory
設(shè)置了maxmemory的選項,假如redis內(nèi)存使用達(dá)到了上限,沒有加上過期時間就會導(dǎo)致數(shù)據(jù)寫滿maxmemory,程序報錯,為了避免類似情況,需要使用內(nèi)存淘汰策略
2.redis過期鍵的刪除策略
如果一個鍵是過期的,那它到了過期時間之后是不是馬上就從內(nèi)存中被刪除了呢?
如果不是,那過期后到底什么時候被刪除呢?是什么操作?
redis三種刪除策略
2.1 立即刪除/定時刪除
立即刪除能保證內(nèi)存中數(shù)據(jù)的最大新鮮度,因為它保證過期鍵值會在過期后馬上被刪除,其所占用的內(nèi)存也會隨之釋放。但是立即刪除對cpu是最不友好的。因為刪除操作會占用cpu的時間,如果剛好碰上了cpu很忙的時候,比如正在做交集或排序等計算的時候,就會給cpu造成額外的壓力,讓CPU心累,時時需要刪除,忙死。
這會產(chǎn)生大量的性能消耗,同時也會影響數(shù)據(jù)的讀取操作
總結(jié):對CPU不友好,用處理器性能換取存儲空間(拿時間換空間)
2.2 惰性刪除
數(shù)據(jù)到達(dá)過期時間,不做處理。等下次訪問該數(shù)據(jù)時,如果未過期,返回數(shù)據(jù) ;發(fā)現(xiàn)已過期,刪除,返回不存在。
惰性刪除策略的缺點是,它對內(nèi)存是最不友好的。
如果一個鍵已經(jīng)過期,而這個鍵又仍然保留在redis中,那么只要這個過期鍵不被訪問,它所占用的內(nèi)存就不會釋放。在使用惰性刪除策略時,如果數(shù)據(jù)庫中有非常多的過期鍵,而這些過期鍵又恰好沒有被訪問到的話,那么它們也許永遠(yuǎn)也不會被刪除(除非用戶手動執(zhí)行FLUSHDB),我們甚至可以將這種情況看作是一種內(nèi)存泄漏 - 無用的垃圾數(shù)據(jù)占用了大量的內(nèi)存。而服務(wù)器卻不會自己去釋放它們,這對于運行狀態(tài)非常依賴于內(nèi)存的Redis服務(wù)器來說,肯定不是一個好消息
總結(jié):對內(nèi)存不友好,用存儲空間換取處理器性能(拿空間換時間),開啟惰性刪除淘汰,lazyfree-lazy-eviction=yes
2.3 定期刪除策略
定期刪除策略是前兩種策略的折中: 定期刪除策略每隔一段時間執(zhí)行一次刪除過期鍵操作并通過限制刪除操作執(zhí)行時長和頻率來減少刪除操作對CPU時間的影響。
周期性輪詢redis庫中的時效性數(shù)據(jù),采用隨機抽取的策略,利用過期數(shù)據(jù)占比的方式控制刪除頻度
特點1:CPU性能占用設(shè)置有峰值,檢測頻度可自定義設(shè)置
特點2:內(nèi)存壓力不是很大,長期占用內(nèi)存的冷數(shù)據(jù)會被持續(xù)清理
總結(jié):周期性抽查存儲空間 (隨機抽查,重點抽查) 舉例: redis默認(rèn)每隔100ms檢查是否有過期的key,有過期key則刪除。注意: redis不是每隔100ms將所有的key檢查一次而是隨機抽取進(jìn)行檢查(如果每隔100ms.全部key進(jìn)行檢查,redis直接進(jìn)去ICU)。因此,如果只采用定期刪除策略,會導(dǎo)致很多key到時間沒有刪除。
定期刪除策略的難點是確定刪除操作執(zhí)行的時長和頻率:如果刪除操作執(zhí)行得太頻繁或者執(zhí)行的時間太長,定期刪除策略就會退化成立即刪除策略,以至于將CPU時間過多地消耗在刪除過期鍵上面。如果刪除操作執(zhí)行得太少,或者執(zhí)行的時間太短,定期刪除策略又會和惰性刪除束略一樣,出現(xiàn)浪費內(nèi)存的情況。因此,如果采用定期刪除策略的話,服務(wù)器必須根據(jù)情況,合理地設(shè)置刪除操作的執(zhí)行時長和執(zhí)行頻率。
上述步驟都過堂了,還有漏洞嗎?
- 定期刪除時,從來沒有被抽查到
- 惰性刪除時,也從來沒有被點中使用過
大量過期的key堆積在內(nèi)存中,導(dǎo)致redis內(nèi)存空間緊張或者很快耗盡
3.緩存淘汰策略
3.1 redis緩存淘汰配置文件
在MEMORY MANAGEMENT中

3.2 LRU和LFU算法的區(qū)別
LRU:最近最少使用頁面置換算法,淘汰最長時間未被使用的頁面,看頁面最后一次被使用到發(fā)生調(diào)度的時間長短,首先淘汰最長時間未被使用的頁面。
LFU:最近最不常用頁面置換算法,淘汰一定時期內(nèi)被訪問次數(shù)最少的頁面,看一定時間段內(nèi)頁面被使用的頻率,淘汰一定時期內(nèi)被訪問次數(shù)最少的頁
比如某次時期Time為10分鐘,如果每分鐘進(jìn)行一次調(diào)頁,主存塊為3(即只能保存3個頁面),若所需頁面走向為2 1 2 1 2 3 4,假設(shè)到頁面4時會發(fā)生缺頁中斷(裝不下導(dǎo)致的緩存淘汰)
若按LRU算法,應(yīng)換頁面1(1頁面最久未被使用),但按LFU算法應(yīng)換頁面3(十分鐘內(nèi),頁面3只使用了一次)
可見LRU關(guān)鍵是看頁面最后一次被使用到發(fā)生調(diào)度的時間長短,而LFU關(guān)鍵是看一定時間段內(nèi)頁面被使用的頻率
3.3 淘汰策略有哪些(R7版本)
- noeviction:不會驅(qū)逐任何key,表示即使內(nèi)存達(dá)到上限也不進(jìn)行置換,所有能引起內(nèi)存增加的命令都會返回error
- allkeys-lru:對所有key使用LRU算法進(jìn)行刪除,優(yōu)先刪除掉最近最不經(jīng)常使用的key,用以保存新數(shù)據(jù)
- volatile-lru:對所有設(shè)置了過期時間的key使用LRU算法進(jìn)行刪除
- allkeys-random:對所有key隨機刪除
- volatile-random:對所有設(shè)置了過期時間的key隨機刪除
- volatile-ttl:刪除馬上要過期的key
- allkeys-lfu:對所有key使用LFU算法進(jìn)行刪除
- volatile-lfu:對所有設(shè)置了過期時間的key使用LFU算法進(jìn)行刪除
對上面淘汰策略的總結(jié)
2個維度:過期鍵中篩選;所有鍵中篩選
- 4個方面:LRU LFU random ttl
- 8個選項
4.淘汰策略選擇
在所有的key都是最近最經(jīng)常使用,那么就需要選擇allkeys-Iru進(jìn)行置換最近最不經(jīng)常使用的key,如果你不確定使用哪種策略,那么推薦使用allkeys-Iru
如果所有的key的訪問概率都是差不多的,那么可以選用allkeys-random策略去置換數(shù)據(jù)
如果對數(shù)據(jù)有足夠的了解,能夠為key指定hint(通過expire/ttl指定),那么可以選擇volatile-ttl進(jìn)行置換
總之,選擇合適的Redis淘汰策略需要考慮應(yīng)用程序的數(shù)據(jù)訪問模式和業(yè)務(wù)需求。
以下是一些具體建議:
- allkeys-lru:適用于緩存場景,優(yōu)先淘汰最近最少使用的鍵,以保留最常訪問的數(shù)據(jù) 。
- volatile-lru:適用于數(shù)據(jù)有過期時間且需要保留熱門數(shù)據(jù)的場景 。
- allkeys-random:適用于數(shù)據(jù)訪問模式不確定或數(shù)據(jù)訪問頻率差別不大的情況 。
- volatile-random:適用于需要淘汰一些即將過期的數(shù)據(jù),但又不希望完全依賴LRU算法的場景 。
- volatile-ttl:適用于需要快速淘汰即將過期數(shù)據(jù)的場景,如緩存即將失效的會話信息 。
- allkeys-lfu 或 volatile-lfu:適用于有短時高頻訪問數(shù)據(jù)的情況 。
- noeviction:默認(rèn)策略,當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時,新寫入操作會報錯,但數(shù)據(jù)不會被刪除 。
- volatile-lfu:適用于設(shè)置了過期時間的鍵中,淘汰訪問頻率最低的鍵 。
選擇淘汰策略時,還應(yīng)考慮以下因素:
- 數(shù)據(jù)的重要性:對于關(guān)鍵業(yè)務(wù)數(shù)據(jù),可能需要更保守的淘汰策略。
- 內(nèi)存資源:如果有足夠的內(nèi)存,可以考慮保留更多的數(shù)據(jù),使用更寬松的淘汰策略。
- 性能影響:某些淘汰策略可能會對性能產(chǎn)生影響,特別是在內(nèi)存不足時。
- 數(shù)據(jù)訪問模式:如果數(shù)據(jù)訪問模式經(jīng)常變化,可能需要定期評估和調(diào)整淘汰策略。
5. 配置淘汰策略
在Redis的配置文件redis.conf中,你可以設(shè)置maxmemory-policy指令來配置淘汰策略。例如,要設(shè)置為使用最近最少使用(LRU)策略,你可以添加以下行:
maxmemory-policy allkeys-lru
啟動時配置
redis-server --maxmemory-policy allkeys-lru
使用命令配置
CONFIG SET maxmemory-policy allkeys-lru
6.redis緩存淘汰策略配置性能建議
配置Redis緩存淘汰策略時,您應(yīng)該考慮以下幾個性能建議:
- 選擇合適的淘汰策略:根據(jù)應(yīng)用程序的特定需求選擇合適的淘汰策略。例如,如果數(shù)據(jù)訪問模式具有明顯的頻率差異,可以選擇
allkeys-lru或allkeys-lfu策略。 - 設(shè)置合理的內(nèi)存使用上限:通過
maxmemory參數(shù)設(shè)置Redis的內(nèi)存使用上限,避免使用超過物理內(nèi)存大小,以免交換到磁盤影響性能。 - 調(diào)整采樣數(shù)量:對于LRU和LFU算法,可以通過
maxmemory-samples參數(shù)控制每次隨機選擇的鍵的數(shù)量,以提高算法的精確度,但也會增加CPU開銷。 - 監(jiān)控內(nèi)存使用:定期使用
INFO memory命令監(jiān)控Redis的內(nèi)存使用情況,評估當(dāng)前的淘汰策略是否合適,并根據(jù)需要進(jìn)行調(diào)整。 - 合理設(shè)置過期時間:為不同的鍵合理設(shè)置過期時間,確保數(shù)據(jù)及時過期,釋放內(nèi)存。
- 使用持久化存儲:對于重要的數(shù)據(jù),可以通過RDB或AOF持久化機制,確保數(shù)據(jù)在內(nèi)存中被淘汰后可以從持久化存儲中恢復(fù)。
- 避免存儲大鍵值對:大鍵值對會影響操作的性能,盡量將大對象分割成多個小對象存儲,避免對大鍵進(jìn)行操作。
- 檢查數(shù)據(jù)持久化策略:根據(jù)業(yè)務(wù)需求合理選擇RDB、AOF或混合持久化方式,非必須情況下可以關(guān)閉持久化以提升性能。
- 使用分布式架構(gòu):當(dāng)數(shù)據(jù)量超過單個Redis實例的內(nèi)存限制時,可以使用Redis集群分片數(shù)據(jù),提高讀寫速度。
7.總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
無法啟動Redis打開redis-server閃退的問題解決辦法
正常開啟redis服務(wù),首先要啟動redis-server.exe,但是閃退,導(dǎo)致無法開啟redis服務(wù),這篇文章主要給大家介紹了關(guān)于無法啟動Redis打開redis-server閃退問題的解決辦法,需要的朋友可以參考下2024-07-07
詳解redis數(shù)據(jù)結(jié)構(gòu)之sds
sds是Simple Dynamic String的縮寫,譯為簡單動態(tài)字符串,redis使用該結(jié)構(gòu)保存字符串,不同于c中的字符串,redis使用該結(jié)構(gòu)來更方便的進(jìn)行字符串的處理,需要的朋友可以參考下2017-05-05

