一篇帶你了解Redis刪除策略
Redis刪除策略

過期數(shù)據(jù)在Redis中所有設(shè)置了TTL的數(shù)據(jù)可能不會立即刪除,Redis會將該鍵帶上過期時間存放到內(nèi)存中的一個Expires字典中。
當(dāng)執(zhí)行TTL命令后會返回其狀態(tài)
- redis 127.0.0.1:6379> TTL key
- -2: Key已經(jīng)過期、被刪除、未定義
- -1: 永久有效
- XX: XX為 key 的剩余生存時間,以秒為單位
這里的已過期數(shù)據(jù),真的刪除了嗎?
數(shù)據(jù)刪除策略
前面說到當(dāng)存儲一個key之后,這個key連同有效期被存儲到Expires字典中,具體什么時候刪除的呢?
通常刪除某個key,我們有如下三種處理方式:
- 定時刪除
- 惰性刪除
- 定期刪除
1. 定時刪除
創(chuàng)建一個定時器,當(dāng)key設(shè)置有過期時間,且過期時間到達(dá)時,由定時器任務(wù)立即執(zhí)行對鍵的刪除操作
優(yōu)點(diǎn):節(jié)省內(nèi)存,到時就刪除,快速釋放掉不必要的內(nèi)存空間
缺點(diǎn):CPU壓力大,無論此時CPU過載有多高,都會占用CPU,會影響Redis服務(wù)器的響應(yīng)時間和吞吐量
總結(jié):用處理器性能換取內(nèi)存空間(時間換空間)
2. 惰性刪除
數(shù)據(jù)到達(dá)過期時間后,不做處理。等下次訪問時,
- 如果未過期,返回數(shù)據(jù)
- 如果已過期,刪除并返回不存在
優(yōu)點(diǎn):節(jié)約CPU性能,發(fā)現(xiàn)必須刪除時才刪除
缺點(diǎn):內(nèi)存壓力大,出現(xiàn)長期占用內(nèi)存空間的數(shù)據(jù)
總結(jié):用內(nèi)存空間換取CPU處理性能(空間換時間)
3. 定期刪除
定時刪除和惰性刪除都太極端了,定期刪除就是一個比較好的折中方案
周期性的輪詢Redis庫中的時效性數(shù)據(jù),采用隨機(jī)抽取的策略,利用過期數(shù)據(jù)占比的方式控制刪除頻度
特點(diǎn):
- CPU占用設(shè)置有峰值,檢測頻度可以自定義
- 內(nèi)存壓力不是很大,長期占用內(nèi)存的冷數(shù)據(jù)會被持續(xù)清理
總結(jié):周期性抽查存儲空間(隨機(jī)抽查,重點(diǎn)抽查)
定期刪除,Redis服務(wù)器啟動初始化時,讀取配置server.hz的值,默認(rèn)為10
每秒執(zhí)行server.hz次serverCorn()->databaseCorn()->activeExpireCycle()
其中activeExpireCycle()對每個Expires[*]逐一檢測,每次執(zhí)行時間為250ms/server.hz
對某個Expires[*]檢測時,隨機(jī)挑選幾個key檢測:
- 如果key超時,刪除key
- 如果一輪中刪除key的數(shù)量>W*25%,循環(huán)該過程(重點(diǎn)抽查)
- 如果一輪中刪除key的數(shù)量
- 其中W取值=ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP的屬性值
4. 刪除策略對比
逐出算法
1. 新數(shù)據(jù)進(jìn)入檢測
當(dāng)新數(shù)據(jù)進(jìn)入Redis時,內(nèi)存不足怎么辦?
Redis使用內(nèi)存存儲數(shù)據(jù),在執(zhí)行每一個命令前,會調(diào)用freeMermoryIfNeeded()檢測內(nèi)存是否充足。如果內(nèi)存不滿足新加入的數(shù)據(jù)的最低存儲要求,Redis要臨時刪除一些數(shù)據(jù)為當(dāng)前指令清理存儲空間。清理數(shù)據(jù)的策略成為逐出算法(內(nèi)存淘汰策略)
注意:逐出數(shù)據(jù)的過程不是100%能夠清理出足夠的可使用的內(nèi)存空間,如果不成功會反復(fù)執(zhí)行。當(dāng)前所有數(shù)據(jù)嘗試執(zhí)行完畢后,如果不能達(dá)到內(nèi)存清理的要求,將出現(xiàn)錯誤信息。
- (error) OOM command not allowed when used memory >'maxmemory'
2. 逐出算法配置
- 最大可用內(nèi)存
- maxmermory
- 說明:占用物理內(nèi)存的比例。默認(rèn)值是0,標(biāo)識不限制。生產(chǎn)上根據(jù)需要設(shè)置,一般在50%以上
- 每次選取待刪除的個數(shù)
- maxmermroy-samples
- 說明:選取待刪除的數(shù)據(jù)時,如果掃描全庫,會嚴(yán)重消耗性能,降低讀寫性能。因?yàn)椴捎秒S機(jī)獲取數(shù)據(jù)的方式作為待檢測刪除數(shù)據(jù)
- 刪除策略
- maxmermory-policy
- 說明:達(dá)到最大內(nèi)存后,對被挑選出來的數(shù)據(jù)進(jìn)行刪除的策略
3. 逐出算法
如果Redis配置了maxmemory和maxmemory-policy策略,則當(dāng)Redis內(nèi)存數(shù)據(jù)達(dá)到maxmemory時,會根據(jù)maxmemory-policy配置來淘汰內(nèi)存數(shù)據(jù),以避免OOM。
根據(jù)maxmemory-policy的配置項(xiàng),執(zhí)行刪除策略時分為兩大類:易失數(shù)據(jù)(設(shè)置過期時間的數(shù)據(jù))、永久數(shù)據(jù)。Redis默認(rèn)值為volatile-lru.
檢測易失數(shù)據(jù)(會過期的數(shù)據(jù)集server.db[i].expries)
- volatile-lru:挑選最近最少使用的數(shù)據(jù)淘汰
- volatile-lfu:挑選最近使用次數(shù)最少的數(shù)據(jù)淘汰
- volatile-random:任意選擇數(shù)據(jù)淘汰
- volatile-ttl:挑選即將過期的數(shù)據(jù)淘汰
檢測全庫數(shù)據(jù)(所有數(shù)據(jù)集server.db[i].dict)
- allkeys-lru:挑選最近最少使用的數(shù)據(jù)淘汰
- allkeys-lfu:挑選最近使用次數(shù)最少的數(shù)據(jù)淘汰
- allkeys-random:任意選擇數(shù)據(jù)淘汰
放棄數(shù)據(jù)淘汰
- no-enviction:禁止數(shù)據(jù)淘汰,會引發(fā)OOM(Out Of Memroy)。Redis4.0默認(rèn)策略
LRU和LFU算法示例
4. 數(shù)據(jù)逐出策略配置依據(jù)
使用info命令數(shù)據(jù)監(jiān)控信息,查詢緩存hit和miss次數(shù),根據(jù)業(yè)務(wù)需要配置逐出算法。
本文轉(zhuǎn)載自微信公眾號「Java養(yǎng)基場」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系Java養(yǎng)基場公眾號。