Redis八大內(nèi)存淘汰策略

導(dǎo)語
Redis的數(shù)據(jù)已經(jīng)設(shè)置了TTL,不是過期就已經(jīng)刪除了嗎?為什么還存在所謂的淘汰策略呢?這個原因我們需要從redis的過期策略聊起。
過期策略
定期刪除
redis 會將每個設(shè)置了過期時(shí)間的 key 放入到一個獨(dú)立的字典中,以后會定期遍歷這個字典來刪除到期的 key。
Redis 默認(rèn)會每秒進(jìn)行十次過期掃描(100ms一次),過期掃描不會遍歷過期字典中所有的 key,而是采用了一種簡單的貪心策略。
1.從過期字典中隨機(jī) 20 個 key;
2.刪除這 20 個 key 中已經(jīng)過期的 key;
3.如果過期的 key 比率超過 1/4,那就重復(fù)步驟 1;
redis默認(rèn)是每隔 100ms就隨機(jī)抽取一些設(shè)置了過期時(shí)間的key,檢查其是否過期,如果過期就刪除。注意這里是隨機(jī)抽取的。為什么要隨機(jī)呢?你想一想假如 redis 存了幾十萬個 key ,每隔100ms就遍歷所有的設(shè)置過期時(shí)間的 key 的話,就會給 CPU 帶來很大的負(fù)載。
惰性刪除
所謂惰性策略就是在客戶端訪問這個key的時(shí)候,redis對key的過期時(shí)間進(jìn)行檢查,如果過期了就立即刪除,不會給你返回任何東西。
定期刪除可能會導(dǎo)致很多過期key到了時(shí)間并沒有被刪除掉。所以就有了惰性刪除。假如你的過期 key,靠定期刪除沒有被刪除掉,還停留在內(nèi)存里,除非你的系統(tǒng)去查一下那個 key,才會被redis給刪除掉。這就是所謂的惰性刪除,即當(dāng)你主動去查過期的key時(shí),如果發(fā)現(xiàn)key過期了,就立即進(jìn)行刪除,不返回任何東西.
總結(jié):定期刪除是集中處理,惰性刪除是零散處理。
為什么需要淘汰策略
有了以上過期策略的說明后,就很容易理解為什么需要淘汰策略了,因?yàn)椴还苁嵌ㄆ诓蓸觿h除還是惰性刪除都不是一種完全精準(zhǔn)的刪除,就還是會存在key沒有被刪除掉的場景,所以就需要內(nèi)存淘汰策略進(jìn)行補(bǔ)充。
Redis 支持的 淘汰策略
## volatile-lru -> Evict using approximated LRU, only keys with an expire set.# 加入鍵的時(shí)候如果過限,首先從設(shè)置了過期時(shí)間的鍵集合中驅(qū)逐最久沒有使用的鍵# allkeys-lru -> Evict any key using approximated LRU.# 加入鍵的時(shí)候,如果過限,首先通過LRU算法驅(qū)逐最久沒有使用的鍵# volatile-lfu -> Evict using approximated LFU, only keys with an expire set.# 從所有配置了過期時(shí)間的鍵中驅(qū)逐使用頻率最少的鍵# allkeys-lfu -> Evict any key using approximated LFU.# 從所有鍵中驅(qū)逐使用頻率最少的鍵# volatile-random -> Remove a random key having an expire set.# 加入鍵的時(shí)候如果過限,從過期鍵的集合中隨機(jī)驅(qū)逐# allkeys-random -> Remove a random key, any key.# 加入鍵的時(shí)候如果過限,從所有key隨機(jī)刪除# volatile-ttl -> Remove the key with the nearest expire time (minor TTL)# 從配置了過期時(shí)間的鍵中驅(qū)逐馬上就要過期的鍵# noeviction -> Don't evict anything, just return an error on write operations.# 當(dāng)內(nèi)存使用超過配置的時(shí)候會返回錯誤,不會驅(qū)逐任何鍵,默認(rèn)配置
說明
LRU指最近使用最少的設(shè)備
LFU表示使用頻率最低
LRU、LFU和volatile ttl都是使用近似隨機(jī)算法實(shí)現(xiàn)的。
注意:對于上述任何策略,當(dāng)沒有合適的鍵進(jìn)行逐出時(shí),Redis將在需要更多內(nèi)存的寫入操作上返回錯誤。這些命令通常用于創(chuàng)建新鍵、添加數(shù)據(jù)或修改現(xiàn)有鍵。例如:SET、INCR、HSET、LPUSH、SUNIONSTORE、SORT(由于STORE參數(shù)),以及EXEC(如果事務(wù)包含任何需要內(nèi)存的命令)。
淘汰策略的配置
默認(rèn)淘汰策略
maxmemory-policy noevictionLRU、LFU和最小TTL算法不是精確算法,而是近似算法(為了節(jié)省內(nèi)存),因此可以對其進(jìn)行調(diào)整以提高速度或精度。默認(rèn)情況下,Redis將檢查五個鍵并選擇最近使用最少的鍵,您可以使用以下配置指令更改樣本大小。
默認(rèn)值為5會產(chǎn)生足夠好的結(jié)果。10非常接近真實(shí)的LRU,但CPU成本更高。3更快,但不是很準(zhǔn)確。
maxmemory-samples 5逐出處理設(shè)計(jì)為在默認(rèn)設(shè)置下運(yùn)行良好。
如果寫入流量異常大,則可能需要增加此值。降低此值可能會降低延遲,但有被逐出的風(fēng)險(xiǎn)處理有效性0=最小延遲,10=默認(rèn)值,100=不考慮延遲的過程
maxmemory-eviction-tenacity 10從Redis 5開始,默認(rèn)情況下,復(fù)制副本將忽略其maxmemory設(shè)置(除非在故障切換后升級為master或手動)。這意味著密鑰的逐出將由主機(jī)處理,在主機(jī)端的密鑰逐出時(shí)將DEL命令發(fā)送到復(fù)制副本。
此行為可確保主副本和副本保持一致,并且通常是您想要的,但是如果您的副本是可寫的,或者您希望副本具有不同的內(nèi)存設(shè)置,并且您確定對副本執(zhí)行的所有寫入都是冪等的,然后,您可以更改此默認(rèn)設(shè)置(但一定要了解您正在做什么)。
請注意,由于復(fù)制副本在默認(rèn)情況下不會退出,因此最終可能會使用比通過maxmemory設(shè)置的內(nèi)存更多的內(nèi)存(復(fù)制副本上的某些緩沖區(qū)可能更大,或者數(shù)據(jù)結(jié)構(gòu)有時(shí)可能占用更多內(nèi)存等等)。因此,請確保監(jiān)視復(fù)制副本,并確保它們有足夠的內(nèi)存,在主副本達(dá)到配置的maxmemory設(shè)置之前,不會出現(xiàn)真正的內(nèi)存不足情況。
replica-ignore-maxmemory yesRedis以兩種方式回收過期的密鑰:當(dāng)發(fā)現(xiàn)這些密鑰過期時(shí)進(jìn)行訪問,以及在后臺,即所謂的“活動過期密鑰”。通過交互方式緩慢地掃描密鑰空間,尋找過期的密鑰進(jìn)行回收,這樣就可以釋放內(nèi)存中過期的密鑰,并且在短時(shí)間內(nèi)再也無法訪問這些密鑰。
expire循環(huán)的默認(rèn)工作將嘗試避免超過10%的過期密鑰仍在內(nèi)存中,并嘗試避免消耗超過總內(nèi)存的25%并增加系統(tǒng)延遲。但是,可以將通常設(shè)置為“1”的過期“努力”增加到更大的值,直到值“10”。在其最大值時(shí),系統(tǒng)將使用更多的CPU、更長的周期(技術(shù)上可能會引入更多的延遲),并將允許系統(tǒng)中仍然存在的已過期密鑰更少。這是內(nèi)存、CPU和延遲之間的折衷。
active-expire-effort 1
