深入 Redis 系列:詳解 Redis 的內(nèi)存管理和緩存數(shù)據(jù)的淘汰機(jī)制
我們知道為了保證較高的性價比,緩存的空間容量必然要小于后端數(shù)據(jù)庫的數(shù)據(jù)總量。隨著要緩存的數(shù)據(jù)量越來越大,有限的緩存空間不可避免地會被寫滿。
解決這個問題就涉及到緩存系統(tǒng)的一個重要機(jī)制,即緩存數(shù)據(jù)的淘汰機(jī)制。數(shù)據(jù)淘汰機(jī)制包括兩步:
- 第一,根據(jù)一定的策略,篩選出對應(yīng)用訪問來說“不重要”的數(shù)據(jù);
- 第二,將這些數(shù)據(jù)從緩存中刪除,為新來的數(shù)據(jù)騰出空間。
然而在正式介紹Redis的緩存淘汰機(jī)制之前,我們不妨關(guān)注一個問題:以系統(tǒng)在DB的數(shù)據(jù)量為基準(zhǔn),你會為你的系統(tǒng)緩存設(shè)置百分之多少的容量?
根據(jù)數(shù)據(jù)訪問的局部性原理,在大多數(shù)的業(yè)務(wù)場景下,80% 的請求實(shí)際只訪問了 20% 的數(shù)據(jù)(八二原理)。
如下圖所示:
藍(lán)線代表了“八二原理”表示的數(shù)據(jù)局部性,而紅線則表示在當(dāng)前應(yīng)用負(fù)載下的數(shù)據(jù)局部性。藍(lán)線描述的是正常情況下有 20% 的數(shù)據(jù)貢獻(xiàn)了 80% 的訪問量。這 80% 的數(shù)據(jù)在訪問量上就形成了一條長長的尾巴,我們也稱為“長尾效應(yīng)”。
真實(shí)業(yè)務(wù)中,用戶的個性化需求越來越多,在一個業(yè)務(wù)應(yīng)用中,不同用戶訪問的內(nèi)容可能差別很大,所以20% 的數(shù)據(jù)可能貢獻(xiàn)不了 80% 的訪問,而剩余的 80% 數(shù)據(jù)反而貢獻(xiàn)了更多的訪問量,我們稱之為重尾效應(yīng)。因此緩存容量占總數(shù)據(jù)量的比例,從 5% 到 40% 的都有,需要結(jié)合應(yīng)用數(shù)據(jù)實(shí)際訪問特征綜合考慮的。一般來說,會建議把緩存容量設(shè)置為總數(shù)據(jù)量的 15% 到 30%,兼顧訪問性能和內(nèi)存空間開銷。
說完了如何設(shè)置緩存容量以及依據(jù)之后,我們開始Redis內(nèi)存管理的正題。
一、Redis內(nèi)存組成、內(nèi)存分配和釋放
Redis的內(nèi)存組成主要包括以下幾個部分:
(1) 自身內(nèi)存:這是Redis服務(wù)器運(yùn)行所需的基本內(nèi)存,包括Redis進(jìn)程不存儲任何key-value時本身所占用的內(nèi)存。
(2) 鍵值對內(nèi)存(key和value):
- key:存儲Redis中每個鍵的內(nèi)存占用。
- 對象內(nèi)存(與value相關(guān)):存儲Redis中每個值(對象)的內(nèi)存占用。Redis中的值可以是字符串、列表、集合、哈希表、有序集合等數(shù)據(jù)類型,每種數(shù)據(jù)類型都有其特定的內(nèi)部表示和內(nèi)存占用。
(3) 緩沖內(nèi)存:
- 客戶端緩沖:用于存儲客戶端請求和響應(yīng)數(shù)據(jù)的緩沖區(qū)。
- 復(fù)制積壓緩沖:用于支持主從復(fù)制功能,存儲復(fù)制過程中的數(shù)據(jù)緩沖區(qū)。
- AOF緩沖:如果啟用了AOF(Append-Only File)持久化,則會有一個緩沖區(qū)用于存儲寫操作,以便在后臺將其寫入磁盤。
(4) 子進(jìn)程內(nèi)存:Redis可能會創(chuàng)建子進(jìn)程來執(zhí)行某些操作,如RDB快照持久化、AOF重寫等。這些子進(jìn)程也會占用相當(dāng)大的內(nèi)存。
(5) 內(nèi)存碎片:由于Redis的內(nèi)存分配器在分配和釋放內(nèi)存時可能會產(chǎn)生碎片,這些碎片會占用額外的內(nèi)存空間。雖然Redis的內(nèi)存分配器(如jemalloc)會盡量減少碎片的產(chǎn)生,但在長時間運(yùn)行或頻繁進(jìn)行內(nèi)存分配和釋放的情況下,仍然可能會產(chǎn)生一定的內(nèi)存碎片。
再說說看Redis的內(nèi)存分配和釋放過程。
Redis的內(nèi)存分配和釋放過程是其內(nèi)存管理的核心環(huán)節(jié),它確保了Redis能夠高效地利用內(nèi)存資源。以下是對Redis內(nèi)存分配和釋放過程的詳細(xì)闡述:
1.內(nèi)存分配過程
(1) 初始化階段:
- 在Redis服務(wù)器啟動時,會初始化一個空的內(nèi)存空間,這個空間稱為“arena”。Arena是一片連續(xù)的內(nèi)存區(qū)域,用于存儲各種數(shù)據(jù)結(jié)構(gòu)和對象。
- Redis使用的Arena大小可以通過配置文件進(jìn)行調(diào)整,默認(rèn)為32MB。
(2) 動態(tài)分配階段:
- 當(dāng)有一個新的對象需要分配內(nèi)存時,Redis會調(diào)用其內(nèi)存分配器(默認(rèn)是jemalloc)進(jìn)行內(nèi)存分配。
- Redis根據(jù)對象的大小選擇合適的Arena進(jìn)行內(nèi)存分配。對象的大小決定了它在Arena中的存儲位置。較小的對象通常存儲在小的Arena中,較大的對象存儲在大的Arena中。
- 在選定的Arena中,Redis會根據(jù)對象的大小分配一塊合適大小的內(nèi)存塊。內(nèi)存塊的大小可能與實(shí)際需要的大小略有不同,這是為了減少內(nèi)存碎片和提高分配效率。
- 分配的內(nèi)存塊會被初始化為指定類型的對象。
(3) 內(nèi)存分配策略:
- Redis的內(nèi)存分配器將內(nèi)存空間劃分為多個部分,如Small class、Large class、Huge class,每個部分又劃分為很多小的內(nèi)存塊單位。這樣,Redis可以采用不同大小的內(nèi)存塊來存儲不同大小的內(nèi)存對象。
- 例如,一個5KB的對象可能會存儲在一個8KB的內(nèi)存塊中,剩下的3KB內(nèi)存就變成了內(nèi)存碎片,但這些碎片仍然可以被jemalloc管理,并在后續(xù)的內(nèi)存分配中重用。
2.內(nèi)存釋放過程
(1) 主動釋放:
- 使用DEL命令可以手動刪除指定的鍵及其值,從而釋放其占用的內(nèi)存。
- FLUSHDB命令用于刪除當(dāng)前數(shù)據(jù)庫中的所有鍵及其值,釋放整個數(shù)據(jù)庫的內(nèi)存。
- FLUSHALL命令則用于刪除所有數(shù)據(jù)庫中的所有鍵及其值,釋放所有數(shù)據(jù)庫的內(nèi)存。
(2) 被動釋放(內(nèi)存淘汰機(jī)制):
- 當(dāng)Redis使用的內(nèi)存達(dá)到maxmemory配置的限制時,Redis會根據(jù)配置的內(nèi)存淘汰策略來釋放內(nèi)存。
- 常見的淘汰策略包括volatile-lru、volatile-ttl、allkeys-lru等,這些策略可以根據(jù)具體的業(yè)務(wù)場景和需求來選擇,以平衡內(nèi)存使用和性能。
(3) 內(nèi)存碎片整理:
- 內(nèi)存碎片化會導(dǎo)致內(nèi)存浪費(fèi)和碎片化問題。Redis提供了defragment命令來進(jìn)行內(nèi)存碎片整理,將內(nèi)存中的碎片空間合并起來,減少內(nèi)存占用。
(4) 對象池管理:
- Redis內(nèi)部維護(hù)了一個對象池,對象的分配和回收都會通過對象池的方式進(jìn)行。
- 當(dāng)一個對象被釋放后,它會被放回對象池,以便下次再次使用。
- 當(dāng)Redis不再需要某個對象時,它會將對象從對象池中移除,并將相應(yīng)的內(nèi)存塊標(biāo)記為空閑狀態(tài)??臻e的內(nèi)存塊可以被其他對象復(fù)用。
(5) 內(nèi)存回收:
- 當(dāng)大量的內(nèi)存塊為空閑狀態(tài)時,Redis會調(diào)用jemalloc的內(nèi)存回收函數(shù)來重新組織已分配的內(nèi)存,以減少內(nèi)存碎片。
二、Redis的鍵值過期處理策略
Redis的鍵值過期策略是內(nèi)存管理中的重要一環(huán)。這里首先需要說一下,可能會有人將Redis的過期策略和淘汰策略給搞混,但其實(shí)兩者并不是一回事。
Redis的過期策略是指對設(shè)置了過期時間的鍵進(jìn)行管理,當(dāng)這些鍵的過期時間到達(dá)時,Redis會采取相應(yīng)的操作來刪除這些鍵。其主要作用是確保Redis中存儲的數(shù)據(jù)是有效的、最新的,并且防止無用數(shù)據(jù)長期占用內(nèi)存資源。其觸發(fā)條件是鍵的過期時間到達(dá),這可以通過Redis的EXPIRE、PEXPIRE等命令來設(shè)置鍵的過期時間。
Redis的淘汰策略是指在內(nèi)存使用達(dá)到上限時,為了保持Redis的穩(wěn)定運(yùn)行和內(nèi)存的有效利用,Redis會采取一系列措施來淘汰部分鍵。淘汰策略的主要作用是防止Redis內(nèi)存溢出,確保Redis能夠持續(xù)穩(wěn)定地提供服務(wù)。淘汰策略的觸發(fā)條件是Redis的內(nèi)存使用達(dá)到或超過其配置的最大內(nèi)存限制(maxmemory)。
從作用對象來說,過期策略作用于設(shè)置了過期時間的鍵,而淘汰策略則可能作用于整個Redis實(shí)例中的所有鍵(取決于具體的淘汰策略)。
Redis的淘汰策略會在下面介紹,這里回到過期策略。
Redis對過期鍵的刪除策略主要包括:惰性刪除和定期刪除。
1.惰性刪除
原理:在客戶端嘗試訪問一個鍵時,Redis會檢查該鍵是否過期。如果已過期,則刪除該鍵并返回“鍵不存在”的響應(yīng);否則,返回該鍵的值。
(1) 優(yōu)點(diǎn):
- 只有在真正需要訪問鍵時才會進(jìn)行刪除操作,減少了不必要的性能開銷。
- 對CPU友好,因?yàn)椴粫趧h除其他無關(guān)的過期鍵上花費(fèi)CPU時間。
(2) 缺點(diǎn):
- 如果數(shù)據(jù)庫中有大量的過期鍵而它們又沒有被訪問到,那么這些鍵將永遠(yuǎn)不會被刪除,可能導(dǎo)致內(nèi)存泄漏。
- 對內(nèi)存不友好,因?yàn)檫^期鍵可能長時間占用內(nèi)存空間。
2.定期刪除
(1) 原理:通過一種定時任務(wù)(如Redis的serverCron)來定期刪除過期鍵。每隔一段時間,Redis會對一部分?jǐn)?shù)據(jù)庫中的鍵進(jìn)行檢查,并刪除其中過期的鍵。
(2) 優(yōu)點(diǎn):
- 通過定期刪除過期鍵,有效減少了內(nèi)存浪費(fèi)。
- 相比定時刪除,對CPU的影響較小,因?yàn)閯h除操作是批量進(jìn)行的,而且頻率可控。
(3) 缺點(diǎn):
- 可能會帶來一定的性能開銷,因?yàn)樾枰ㄆ诒闅v數(shù)據(jù)庫來檢查過期鍵。
- 確定刪除操作執(zhí)行的時長和頻率是一個難點(diǎn),需要根據(jù)實(shí)際情況進(jìn)行權(quán)衡和調(diào)整。
三、Redis的鍵值淘汰策略
首先為什么Redis需要淘汰策略呢?如果讓大家回答這個問題,可能大家想到的可能只有:因?yàn)閮?nèi)存滿了,所以需要根據(jù)一定的策略淘汰掉一些舊的或者少用的鍵值來存儲新的或者常用的鍵值。但其實(shí)還可以從性能、數(shù)據(jù)一致性、內(nèi)存成本和應(yīng)對突發(fā)流量等角度來回答這個問題。
Redis需要淘汰策略的原因主要與其內(nèi)存管理的特性和應(yīng)用場景有關(guān)。以下是幾個關(guān)鍵的原因:
- 內(nèi)存限制:Redis是一個內(nèi)存數(shù)據(jù)庫,它依賴于內(nèi)存來存儲數(shù)據(jù)。然而,服務(wù)器的內(nèi)存資源是有限的。當(dāng)Redis使用的內(nèi)存達(dá)到某個上限(通常由maxmemory配置參數(shù)指定)時,為了避免內(nèi)存溢出和服務(wù)器崩潰,Redis需要一種機(jī)制來騰出空間,這就是淘汰策略的作用。
- 性能優(yōu)化:通過淘汰策略,Redis可以移除那些不常用或不再需要的數(shù)據(jù),從而保持內(nèi)存中的數(shù)據(jù)是活躍和有用的。這有助于提高Redis的查詢性能和響應(yīng)速度,因?yàn)镽edis可以更快地定位到用戶需要的數(shù)據(jù)。
- 成本考慮:雖然增加服務(wù)器的內(nèi)存可以容納更多的數(shù)據(jù),但這也會增加硬件成本。通過合理的淘汰策略,Redis可以在不犧牲太多性能的情況下,在有限的內(nèi)存資源上運(yùn)行,從而降低了成本。
- 數(shù)據(jù)一致性:在某些情況下,Redis中的數(shù)據(jù)可能是臨時或緩存性質(zhì)的。對于這些數(shù)據(jù),使用淘汰策略可以確保Redis始終存儲最新的或最重要的數(shù)據(jù),而不是保留過時的或不再需要的數(shù)據(jù)。
- 應(yīng)對突發(fā)流量:在突發(fā)流量或高并發(fā)場景下,Redis可能會接收到大量的數(shù)據(jù)請求。通過淘汰策略,Redis可以在內(nèi)存資源緊張時自動釋放一些數(shù)據(jù),從而確保系統(tǒng)能夠繼續(xù)穩(wěn)定運(yùn)行,而不會因內(nèi)存耗盡而崩潰。
那么Redis的整體淘汰鍵值的流程是怎么樣的呢?
Redis淘汰策略的流程主要涉及內(nèi)存檢測、淘汰策略選擇、數(shù)據(jù)取樣、淘汰池維護(hù)、數(shù)據(jù)刪除等步驟。以下是詳細(xì)的流程說明:
1.內(nèi)存檢測
(1) 周期性內(nèi)存檢查:
- Redis會周期性地檢查當(dāng)前使用的內(nèi)存是否超過了配置的maxmemory限制。
- 這一檢查是通過調(diào)用freeMemoryIfNeeded函數(shù)來實(shí)現(xiàn)的。
(2) 判斷是否需要淘汰數(shù)據(jù):
- 如果當(dāng)前內(nèi)存使用量沒有超過maxmemory,則不需要進(jìn)行淘汰操作。
- 如果超過了maxmemory,則需要根據(jù)配置的淘汰策略來選擇要淘汰的數(shù)據(jù)。
2.淘汰策略選擇
(1) 配置淘汰策略:
- Redis提供了多種淘汰策略,如volatile-lru、allkeys-lru、volatile-lfu(如果Redis版本支持)、allkeys-lfu、volatile-ttl、volatile-random、allkeys-random以及no-eviction等。
- 這些策略可以在Redis的配置文件中通過maxmemory-policy參數(shù)進(jìn)行配置。
(2) 選擇淘汰策略:
- 根據(jù)配置的淘汰策略,Redis會決定是從設(shè)置了過期時間的數(shù)據(jù)集中選擇(如volatile-lru),還是從所有數(shù)據(jù)中選擇(如allkeys-lru)。
- 同時,根據(jù)策略的不同,Redis會選擇不同的算法來確定要淘汰的數(shù)據(jù),如LRU算法、LFU算法等。
3.數(shù)據(jù)取樣
(1) 隨機(jī)取樣:
- Redis會從數(shù)據(jù)集(或設(shè)置了過期時間的數(shù)據(jù)集)中隨機(jī)選擇一定數(shù)量的key作為取樣數(shù)據(jù)。
- 取樣的數(shù)量可以通過maxmemory-samples參數(shù)進(jìn)行配置,默認(rèn)值為5。
(2) 計算訪問頻率或時間:
- 對于LFU策略,Redis會計算每個取樣數(shù)據(jù)的訪問頻率。
- 對于LRU策略,Redis會記錄每個取樣數(shù)據(jù)的最近訪問時間。
3.淘汰池維護(hù)
(1) 淘汰池初始化:
- Redis會維護(hù)一個淘汰池(eviction pool),用于存儲待淘汰的key。
- 淘汰池的大小是固定的,默認(rèn)為16。
(2) 數(shù)據(jù)比較與排序:
- 將取樣數(shù)據(jù)與淘汰池中的數(shù)據(jù)進(jìn)行比較,根據(jù)淘汰策略(如LRU、LFU等)來確定哪些數(shù)據(jù)更適合被淘汰。
- 將更適合被淘汰的數(shù)據(jù)放入淘汰池(例如如果按照LRU策略來淘汰的話,那么如果取樣數(shù)據(jù)的最后訪問時間比淘汰池中的最晚訪問的數(shù)據(jù)的訪問事件要早,那么這個取樣數(shù)據(jù)就會被放入淘汰池),并按照適合的程度對淘汰吃中的數(shù)據(jù)進(jìn)行排序。
4.數(shù)據(jù)刪除
(1) 選擇最佳淘汰數(shù)據(jù):
- 從淘汰池中選擇最適合被淘汰的數(shù)據(jù)(通常是排序最靠后的數(shù)據(jù))。
(2) 刪除數(shù)據(jù):
- 從Redis數(shù)據(jù)庫中刪除選中的key及其對應(yīng)的value。
- 將刪除操作的消息發(fā)布到本地(AOF持久化)和從機(jī)(主從連接)。
(3) 更新內(nèi)存使用量:
- 刪除數(shù)據(jù)后,更新Redis的內(nèi)存使用量。
- 如果刪除后內(nèi)存使用量仍然超過maxmemory,則繼續(xù)執(zhí)行淘汰流程,直到內(nèi)存使用量滿足要求為止。
上面的Redis淘汰流程中說到,Redis會根據(jù)具體的淘汰策略來決定哪些鍵值應(yīng)該被淘汰,下面介紹一下Redis的淘汰策略。
其實(shí)Redis的鍵值淘汰策略遵循主流的內(nèi)存淘汰算法:LFU和LRU算法。所以在說具體的淘汰策略之前,我會先簡單介紹下這兩種算法的特點(diǎn)和實(shí)現(xiàn)。
5.LRU算法
(1) 原理:
LRU算法根據(jù)數(shù)據(jù)的訪問時間來決定哪些數(shù)據(jù)會被淘汰。其核心思想是:最久未被訪問的數(shù)據(jù)被認(rèn)為是最不常用的數(shù)據(jù),應(yīng)該被優(yōu)先淘汰。
(2) 實(shí)現(xiàn)方式:
Redis使用雙向鏈表和哈希表來實(shí)現(xiàn)LRU算法。鏈表用于維護(hù)數(shù)據(jù)的使用順序,鏈表的頭部表示最新使用的數(shù)據(jù),而鏈表的尾部表示最舊的數(shù)據(jù)。哈希表則用于加快數(shù)據(jù)的查找速度,哈希表的鍵是數(shù)據(jù)的鍵,值是指向雙向鏈表節(jié)點(diǎn)的指針。
當(dāng)有數(shù)據(jù)被訪問時,Redis會將該數(shù)據(jù)從鏈表中當(dāng)前位置移動到鏈表頭部。這樣一來,經(jīng)常被訪問的數(shù)據(jù)就會一直保持在鏈表頭部,而少訪問的數(shù)據(jù)就會逐漸向鏈表尾部移動。當(dāng)需要淘汰數(shù)據(jù)時,只需要選擇鏈表尾部的數(shù)據(jù)即可。
(3) 特點(diǎn):
LRU算法實(shí)現(xiàn)簡單,能夠較好地保留熱數(shù)據(jù)(即經(jīng)常被訪問的數(shù)據(jù)),提高命中率。
但是,LRU算法可能會受到突發(fā)性訪問模式的影響,即某些數(shù)據(jù)可能只是偶爾被訪問一次,但根據(jù)LRU算法,這些數(shù)據(jù)可能會被保留在內(nèi)存中較長時間。
(4) 適用場景:
LRU算法適用于訪問頻率分布相對均勻的場景,能夠較好地平衡內(nèi)存使用和性能需求。
6.LFU算法
(1) 原理:
LFU算法根據(jù)數(shù)據(jù)被訪問的頻率來決定哪些數(shù)據(jù)會被淘汰。其核心思想是:使用頻率越低的數(shù)據(jù)被認(rèn)為是最不常用的數(shù)據(jù),應(yīng)該被優(yōu)先淘汰。
(2) 實(shí)現(xiàn)方式:
Redis使用哈希表和最小堆(或其他數(shù)據(jù)結(jié)構(gòu),如雙向鏈表和計數(shù)器等)來實(shí)現(xiàn)LFU算法。哈希表用于存儲數(shù)據(jù)和其對應(yīng)的訪問頻率,而最小堆則用于快速找到訪問頻率最低的數(shù)據(jù)。
當(dāng)有數(shù)據(jù)被訪問時,Redis會更新該數(shù)據(jù)在哈希表中的訪問頻率。當(dāng)需要淘汰數(shù)據(jù)時,Redis會從最小堆中選擇訪問頻率最低的數(shù)據(jù)進(jìn)行刪除。下圖展示了LFU算法執(zhí)行的過程。
(3) 特點(diǎn):
LFU算法能夠更準(zhǔn)確地識別出那些真正不常用的數(shù)據(jù),并將其淘汰掉。
但是,LFU算法可能會受到訪問頻率的波動影響,即某些數(shù)據(jù)可能在某個時間段內(nèi)被頻繁訪問,但之后就不再被訪問了。這些數(shù)據(jù)可能會因?yàn)橹暗脑L問頻率較高而被保留在內(nèi)存中較長時間。
(4) 適用場景:
LFU算法適用于某些數(shù)據(jù)的訪問頻率明顯高于其他數(shù)據(jù)的場景,能夠更準(zhǔn)確地保留熱門數(shù)據(jù)并淘汰冷門數(shù)據(jù)。
三、對比與選擇
對比:
- LRU算法主要關(guān)注數(shù)據(jù)的訪問時間,而LFU算法主要關(guān)注數(shù)據(jù)的訪問頻率。
- LRU算法實(shí)現(xiàn)簡單且高效,但可能受到突發(fā)性訪問模式的影響;而LFU算法能夠更準(zhǔn)確地識別出不常用的數(shù)據(jù),但可能受到訪問頻率波動的影響。
了解了LRU和LFU算法是怎么一回事之后,我們再看看Redis具體的淘汰策略。Redis的主要淘汰機(jī)制及其適用場景如下:
(1) noeviction(不淘汰)
描述:當(dāng)內(nèi)存不足時,對寫請求不再提供服務(wù),直接返回錯誤(但DEL請求和部分特殊請求除外)。
適用場景:適合需要嚴(yán)格控制內(nèi)存使用量的場景,但可能導(dǎo)致寫入失敗。當(dāng)數(shù)據(jù)完整性或?qū)懭氩僮鞯闹匾愿哂诰彺嫘阅軙r,可以選擇此策略。
(2) allkeys-lru(從所有key中使用LRU算法淘汰)
描述:使用LRU(Least Recently Used,最近最少使用)算法從所有key中選擇最久未使用的數(shù)據(jù)進(jìn)行淘汰。
適用場景:適用于緩存場景,確保常用數(shù)據(jù)優(yōu)先保留,不區(qū)分是否設(shè)置過期時間。當(dāng)數(shù)據(jù)訪問模式具有明顯的時間局部性(即最近被訪問的數(shù)據(jù)更有可能在未來被訪問)時,此策略效果較好。
(3) volatile-lru(從設(shè)置了過期時間的key中使用LRU算法淘汰)
描述:僅對設(shè)置了過期時間的key使用LRU算法進(jìn)行淘汰。
適用場景:適合需要定期清理過期數(shù)據(jù)的場景,同時希望保留最近使用的數(shù)據(jù)。當(dāng)數(shù)據(jù)具有明確的過期時間,并且希望確保在內(nèi)存緊張時優(yōu)先淘汰這些過期數(shù)據(jù)中較久未使用的部分時,此策略較為合適。
(4) allkeys-random(從所有key中隨機(jī)淘汰)
描述:從所有key中隨機(jī)選擇數(shù)據(jù)進(jìn)行淘汰。
適用場景:適用于緩存策略不明確的場景,或者當(dāng)數(shù)據(jù)訪問模式?jīng)]有明顯的規(guī)律時。此策略較為隨機(jī),不保證常用數(shù)據(jù)優(yōu)先保留。
(5) volatile-random(從設(shè)置了過期時間的key中隨機(jī)淘汰)
描述:僅對設(shè)置了過期時間的key進(jìn)行隨機(jī)淘汰。
適用場景:適合不確定熱點(diǎn)數(shù)據(jù)的場景,但隨機(jī)淘汰方式可能不適合對性能有要求的應(yīng)用。當(dāng)數(shù)據(jù)具有過期時間,且對淘汰哪部分?jǐn)?shù)據(jù)沒有特定要求時,可以選擇此策略。
(6) volatile-ttl(淘汰過期時間剩余最短的)
描述:在設(shè)置了過期時間的key中,淘汰過期時間剩余最短的。
適用場景:適合短時間內(nèi)需要清除快過期的數(shù)據(jù),但不適合熱點(diǎn)數(shù)據(jù)訪問的場景。當(dāng)希望優(yōu)先淘汰那些即將過期的數(shù)據(jù)時,此策略較為合適。
(7) allkeys-lfu(從所有key中使用LFU算法淘汰,如果Redis版本支持)
描述:使用LFU(Least Frequently Used,最少頻率使用)算法從所有key中選擇訪問頻率最低的數(shù)據(jù)進(jìn)行淘汰。
適用場景:適用于訪問模式穩(wěn)定但不同key的訪問頻率差異明顯的場景。當(dāng)希望保留那些經(jīng)常被訪問的數(shù)據(jù),并淘汰那些很少被訪問的數(shù)據(jù)時,此策略效果較好。
(8) volatile-lfu(從設(shè)置了過期時間的key中使用LFU算法淘汰,如果Redis版本支持)
描述:僅對設(shè)置了過期時間的key使用LFU算法進(jìn)行淘汰。
適用場景:適合需要在一定時間內(nèi)淘汰使用頻率較低的數(shù)據(jù)的場景,同時這些數(shù)據(jù)具有明確的過期時間。當(dāng)希望確保在內(nèi)存緊張時優(yōu)先淘汰那些過期數(shù)據(jù)中訪問頻率較低的部分時,此策略較為合適。