Redis 內(nèi)存淘汰策略深度解析(最新推薦)
Redis 作為高性能的內(nèi)存數(shù)據(jù)庫,其內(nèi)存資源的高效管理直接關(guān)系到系統(tǒng)的穩(wěn)定性和性能。當(dāng) Redis 的內(nèi)存使用達(dá)到配置的最大值(maxmemory)時,新的寫入操作將觸發(fā)內(nèi)存淘汰機(jī)制(Eviction Policy),以釋放空間存儲新數(shù)據(jù)。本文將深入探討 Redis 的內(nèi)存淘汰策略、實(shí)現(xiàn)原理、適用場景及最佳實(shí)踐。
一、 內(nèi)存淘汰策略概述
Redis 的內(nèi)存淘汰策略決定了在內(nèi)存不足時,如何選擇需要刪除的鍵來釋放空間。這些策略可以分為兩大類:
- 基于過期時間的淘汰?(volatile-*):僅針對設(shè)置了過期時間的鍵。
- 全局淘汰?(allkeys-*):針對所有鍵,無論是否設(shè)置過期時間。
Redis 支持以下 8 種內(nèi)存淘汰策略:
?noeviction:默認(rèn)策略,禁止寫入新數(shù)據(jù),直接返回錯誤。
?volatile-lru:淘汰最近最少使用(LRU)的設(shè)置了過期時間的鍵。
?volatile-lfu:淘汰最不經(jīng)常使用(LFU)的設(shè)置了過期時間的鍵。
?volatile-random:隨機(jī)淘汰設(shè)置了過期時間的鍵。
?volatile-ttl:優(yōu)先淘汰剩余生存時間(TTL)最短的鍵。
?allkeys-lru:淘汰所有鍵中最近最少使用的鍵。
?allkeys-lfu:淘汰所有鍵中最不經(jīng)常使用的鍵。
?allkeys-random:隨機(jī)淘汰任意鍵。
二、內(nèi)存淘汰策略詳解
2.1 ?noeviction(不淘汰)?
?行為:當(dāng)內(nèi)存不足時,拒絕所有寫入命令(如 SET、LPUSH),但允許讀取操作。
?適用場景:適用于數(shù)據(jù)不可丟失的場景(如持久化存儲),需確保內(nèi)存足夠或配合持久化機(jī)制。
?缺點(diǎn):若內(nèi)存不足且無持久化,可能導(dǎo)致服務(wù)不可用。
2.2 ?LRU(Least Recently Used)?
?原理:淘汰最近最久未被訪問的鍵。
?Redis 實(shí)現(xiàn):Redis 使用近似 LRU 算法,通過隨機(jī)采樣(默認(rèn)取 5 個鍵)選擇最久未使用的鍵,而非遍歷所有鍵,以減少計算開銷。
?適用場景:適用于緩存場景,優(yōu)先保留熱點(diǎn)數(shù)據(jù)。
?命令示例:
CONFIG SET maxmemory-policy volatile-lru # 針對帶過期時間的鍵 CONFIG SET maxmemory-policy allkeys-lru # 針對所有鍵
2.3 ?LFU(Least Frequently Used)?
?原理:淘汰訪問頻率最低的鍵(Redis 4.0 引入)。
?Redis 實(shí)現(xiàn):通過計數(shù)器統(tǒng)計鍵的訪問頻率,并隨時間衰減歷史計數(shù),避免長期累積導(dǎo)致無法淘汰舊鍵。
?適用場景:適合長期緩存,如高頻訪問的靜態(tài)數(shù)據(jù)。
?命令示例:
CONFIG SET maxmemory-policy volatile-lfu # 針對帶過期時間的鍵 CONFIG SET maxmemory-policy allkeys-lfu # 針對所有鍵
2.4 ?TTL(Time To Live)?
?原理:優(yōu)先淘汰剩余生存時間(TTL)最短的鍵。
?適用場景:適用于明確知道鍵生命周期的場景(如臨時會話數(shù)據(jù))。
?限制:僅對設(shè)置了過期時間的鍵生效。
?命令示例:
CONFIG SET maxmemory-policy volatile-ttl
2.5 ?Random(隨機(jī)淘汰)?
?原理:隨機(jī)選擇鍵進(jìn)行淘汰。
?適用場景:內(nèi)存壓力大且數(shù)據(jù)重要性均等時,快速釋放內(nèi)存。
?命令示例:
CONFIG SET maxmemory-policy volatile-random # 針對帶過期時間的鍵 CONFIG SET maxmemory-policy allkeys-random # 針對所有鍵
三、 內(nèi)存淘汰的底層實(shí)現(xiàn)
3.1 ?LRU/LFU 的近似算法
- Redis 通過 ?evictionPoolEntry?結(jié)構(gòu)維護(hù)候選淘汰鍵池。每次淘汰時,隨機(jī)采樣一組鍵,更新其訪問時間或頻率信息,選擇最不活躍的鍵刪除。
- ?LRU 時鐘:Redis 使用全局 24 位時鐘(精度為秒)記錄鍵的最近訪問時間。內(nèi)存中每個對象存儲與全局時鐘的差值(lru字段),而非精確時間戳。
- ?LFU 計數(shù)器:每個鍵的 lru 字段被拆分為兩部分:
- 高 16 位:最近訪問時間的分鐘級精度。
- 低 8 位:訪問頻率計數(shù)器(0~255),通過概率遞增,隨時間衰減。
3.2 ?淘汰流程
- 客戶端執(zhí)行寫入命令觸發(fā)內(nèi)存檢查。
- Redis 檢查 maxmemory 是否已超出。
- 根據(jù)配置的策略選擇待淘汰鍵。
- 刪除鍵并觸發(fā)相關(guān)事件(如 evicted 通知)。
四、 如何選擇合適的內(nèi)存淘汰策略?
4.1 ?緩存場景
?推薦策略:allkeys-lru 或 allkeys-lfu
?理由:優(yōu)先保留熱點(diǎn)數(shù)據(jù),最大化緩存命中率。
4.2 ?持久化存儲
?推薦策略:noeviction(需確保內(nèi)存足夠或啟用持久化)。
?替代方案:若允許部分?jǐn)?shù)據(jù)丟失,可使用 volatile-lru 結(jié)合過期時間。
4.3 ?臨時數(shù)據(jù)場景
?推薦策略:volatile-ttl
?理由:自動清理生命周期明確的數(shù)據(jù)(如驗(yàn)證碼、會話信息)。
4.4 ?混合型數(shù)據(jù)
?推薦策略:allkeys-lru + 部分鍵設(shè)置過期時間。
?示例:電商系統(tǒng)中,商品詳情用 allkeys-lru 緩存,購物車數(shù)據(jù)設(shè)置 TTL。
五、最佳實(shí)踐與注意事項(xiàng)
5.1 ?配置建議
?設(shè)置合理的 maxmemory:通常為物理內(nèi)存的 80%~90%,避免 OOM。
?監(jiān)控內(nèi)存使用:
INFO memory # 查看內(nèi)存指標(biāo)(used_memory、maxmemory) INFO stats # 查看 evicted_keys(淘汰鍵數(shù)量)
5.2 ?避免大規(guī)模淘汰
?分片設(shè)計:通過集群分散數(shù)據(jù),減少單個節(jié)點(diǎn)的內(nèi)存壓力。
?預(yù)熱緩存:重啟后預(yù)加載高頻數(shù)據(jù),避免冷啟動時集中淘汰。
5.3 ?常見誤區(qū)
?volatile-ttl 不依賴惰性刪除:該策略僅在內(nèi)存不足時觸發(fā),仍需依賴定期/惰性刪除清理過期鍵。
?LFU 計數(shù)器并非精確值:訪問頻率通過概率遞增,適用于相對比較而非絕對計數(shù)。
六、總結(jié)
Redis 的內(nèi)存淘汰策略是平衡內(nèi)存使用與性能的關(guān)鍵機(jī)制。理解不同策略的原理和適用場景,結(jié)合業(yè)務(wù)需求合理配置,可顯著提升系統(tǒng)的穩(wěn)定性和效率。在高并發(fā)場景下,建議通過監(jiān)控工具(如 RedisInsight、Prometheus)實(shí)時跟蹤內(nèi)存和淘汰指標(biāo),動態(tài)調(diào)整策略和資源配置。
通過本文的深度解析,希望您能掌握 Redis 內(nèi)存淘汰的核心機(jī)制,并在實(shí)踐中靈活運(yùn)用,構(gòu)建高效可靠的 Redis 服務(wù)。
參考資料
Redis 官方文檔:https://redis.io/docs/reference/eviction/
《Redis 設(shè)計與實(shí)現(xiàn)》——黃健宏
Redis 源碼解析(evict.c、object.c)
到此這篇關(guān)于Redis 內(nèi)存淘汰策略深度解析的文章就介紹到這了,更多相關(guān)Redis 內(nèi)存淘汰策略內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于redis狀態(tài)監(jiān)控和性能調(diào)優(yōu)詳解
Redis是一種高級key-value數(shù)據(jù)庫。它跟memcached類似,不過數(shù)據(jù)可以持久化,而且支持的數(shù)據(jù)類型很豐富。有字符串,鏈表、哈希、集合和有序集合5種。下面這篇文章主要給大家介紹了關(guān)于redis狀態(tài)監(jiān)控和性能調(diào)優(yōu)的相關(guān)資料,需要的朋友可以參考下。2017-09-09Redis中l(wèi)ua腳本實(shí)現(xiàn)及其應(yīng)用場景
本文主要介紹了Redis中l(wèi)ua腳本實(shí)現(xiàn)及其應(yīng)用場景,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04Redis與MySQL數(shù)據(jù)一致性問題的策略模式及解決方案
開發(fā)中,一般會使用Redis緩存一些常用的熱點(diǎn)數(shù)據(jù)用來減少數(shù)據(jù)庫IO,提高系統(tǒng)的吞吐量,本文將給大家介紹了Redis與MySQL數(shù)據(jù)一致性問題的策略模式及解決方案,文中通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下2024-07-07詳解Redis中key的命名規(guī)范和值的命名規(guī)范
這篇文章主要介紹了詳解Redis中key的命名規(guī)范和值的命名規(guī)范,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12Windows安裝Redis并添加本地自啟動服務(wù)的實(shí)例詳解
這篇文章主要介紹了Windows安裝Redis并添加本地自啟動服務(wù)的實(shí)例詳解,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-11-11Redis底層數(shù)據(jù)結(jié)構(gòu)詳解
這篇文章主要介紹了Redis底層數(shù)據(jù)結(jié)構(gòu),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-08-08