Redis數(shù)據(jù)刪除與淘汰策略從原理到實戰(zhàn)指南
Redis 作為高性能的內(nèi)存數(shù)據(jù)庫,所有數(shù)據(jù)都存儲在內(nèi)存中,而內(nèi)存資源是有限的——這就引出了兩個核心問題:過期數(shù)據(jù)如何刪除?內(nèi)存滿了之后新數(shù)據(jù)如何存儲?
這兩個問題分別對應(yīng) Redis 的「數(shù)據(jù)刪除策略」和「數(shù)據(jù)淘汰策略」,二者相輔相成,共同決定了 Redis 的性能、內(nèi)存利用率和數(shù)據(jù)一致性。很多開發(fā)者在使用 Redis 時,容易混淆這兩個概念,甚至因配置不當導(dǎo)致內(nèi)存溢出、數(shù)據(jù)丟失或性能瓶頸。
本篇博客將從「基礎(chǔ)概念鋪墊」到「策略細節(jié)拆解」,再到「底層原理」和「實戰(zhàn)配置」,把 Redis 數(shù)據(jù)刪除與淘汰策略講透,無論是面試備考還是生產(chǎn)實踐,都能直接套用。
一、前置基礎(chǔ):先搞懂2個核心前提
在講解具體策略前,必須先明確兩個基礎(chǔ)概念,否則容易理解偏差:
1. 過期數(shù)據(jù) vs 非過期數(shù)據(jù)
Redis 支持給 key 設(shè)置過期時間(通過 EXPIRE、PEXPIRE 等命令),過期數(shù)據(jù)是指「到達預(yù)設(shè)過期時間但尚未被刪除的 key」;非過期數(shù)據(jù)則是沒有設(shè)置過期時間,或未到達過期時間的 key。
注意:過期數(shù)據(jù)不一定會被立即刪除,Redis 不會實時監(jiān)控每一個 key 的過期狀態(tài)(否則會消耗大量CPU),而是通過特定策略“懶”刪除或“批量”刪除。
2. 數(shù)據(jù)刪除 vs 數(shù)據(jù)淘汰
這是最容易混淆的兩個概念,一句話區(qū)分:
- 數(shù)據(jù)刪除:針對「過期數(shù)據(jù)」的清理操作,核心是“刪除過期的key”,釋放內(nèi)存;
- 數(shù)據(jù)淘汰:針對「內(nèi)存滿了之后」的處理操作,核心是“刪除部分非過期數(shù)據(jù)”,為新數(shù)據(jù)騰出內(nèi)存(只有當內(nèi)存達到 maxmemory 閾值時才會觸發(fā))。
簡單說:刪除是“清理過期垃圾”,淘汰是“內(nèi)存不夠時騰地方”。
二、Redis 數(shù)據(jù)刪除策略(清理過期數(shù)據(jù))
Redis 沒有采用“實時刪除”(每一個 key 過期就立即刪除),因為實時刪除會導(dǎo)致 CPU 利用率飆升(尤其是過期 key 極多的場景),影響 Redis 核心讀寫性能。
實際上,Redis 采用「三種刪除策略結(jié)合」的方式,兼顧 CPU 性能和內(nèi)存利用率,分別是:惰性刪除、定期刪除、主動刪除。
1. 惰性刪除(Lazy Expiration):最“懶”的刪除,按需觸發(fā)
核心邏輯
Redis 不主動監(jiān)控 key 的過期時間,只有當「用戶主動訪問某個 key」時,才會檢查該 key 是否過期:
- 如果 key 未過期:正常返回數(shù)據(jù);
- 如果 key 已過期:立即刪除該 key,返回 null(或不存在)。
優(yōu)點
極致節(jié)省 CPU 資源:只在“訪問時”才檢查過期,不占用額外的 CPU 時間,對 Redis 核心讀寫性能幾乎無影響。
缺點
內(nèi)存浪費嚴重:如果一個過期 key 長期不被訪問,它會一直占用內(nèi)存,直到被訪問時才會被刪除。極端情況下,大量過期 key 堆積會導(dǎo)致內(nèi)存溢出(這也是為什么需要配合其他刪除策略)。
舉個例子:設(shè)置 100 萬個 key,過期時間為 1 小時,1 小時后所有 key 都過期,但如果沒人訪問這些 key,它們會一直占用內(nèi)存,直到被定期刪除或主動刪除清理。
2. 定期刪除(Periodic Expiration):折中方案,批量檢查
核心邏輯
Redis 會每隔一段時間(默認 100ms,可通過配置調(diào)整),隨機抽取一部分過期 key 進行檢查,如果發(fā)現(xiàn)過期,就刪除它們。具體流程:
- 每次執(zhí)行定期刪除時,從過期字典(存儲所有過期 key 的字典)中隨機抽取 N 個 key;
- 檢查這些 key 是否過期,刪除所有過期的 key;
- 如果刪除的 key 數(shù)量超過 N 的 25%,則重復(fù)步驟 1(說明當前過期 key 較多,需要繼續(xù)清理);否則結(jié)束本次定期刪除。
關(guān)鍵配置
定期刪除的頻率由配置 hz 控制(默認 hz=10),hz 的值表示「Redis 每秒執(zhí)行定期任務(wù)的次數(shù)」:
- hz 值越大,定期刪除越頻繁,過期 key 清理越及時,但 CPU 占用越高;
- hz 值越小,CPU 占用越低,但過期 key 清理越慢,內(nèi)存浪費越嚴重。
生產(chǎn)環(huán)境建議:hz 保持默認 10 即可,若內(nèi)存壓力較大,可調(diào)整為 20(需注意 CPU 負載)。
優(yōu)點
折中了 CPU 和內(nèi)存:既不會像惰性刪除那樣浪費大量內(nèi)存,也不會像實時刪除那樣占用過多 CPU。
缺點
存在“漏刪”風險:因為是隨機抽取檢查,可能有部分過期 key 一直未被抽取到,從而長期占用內(nèi)存(但可以通過惰性刪除彌補:只要用戶訪問,就會被刪除)。
3. 主動刪除(Active Expiration):內(nèi)存不足時的強制清理
核心邏輯
當 Redis 內(nèi)存使用達到 maxmemory(最大內(nèi)存閾值)時,會觸發(fā)「主動刪除」——優(yōu)先刪除過期 key,釋放內(nèi)存,避免內(nèi)存溢出。
注意:主動刪除是「淘汰策略的前置步驟」:當內(nèi)存滿時,Redis 會先嘗試刪除所有過期 key;如果刪除完所有過期 key 后,內(nèi)存仍然不足,才會執(zhí)行「數(shù)據(jù)淘汰策略」(刪除非過期 key)。
觸發(fā)條件
只有當內(nèi)存使用量 ≥ maxmemory 時,才會觸發(fā)主動刪除;如果內(nèi)存未達到閾值,即使有大量過期 key,也只會通過惰性刪除和定期刪除清理。
總結(jié):三種刪除策略的協(xié)同工作
Redis 不是單一使用某一種刪除策略,而是三者結(jié)合:
- 日常情況下,通過「惰性刪除」保證 CPU 高效,避免不必要的檢查;
- 每隔一段時間,通過「定期刪除」批量清理部分過期 key,減少內(nèi)存浪費;
- 當內(nèi)存不足時,通過「主動刪除」優(yōu)先清理所有過期 key,為新數(shù)據(jù)騰出空間;
- 若主動刪除后內(nèi)存仍不足,則執(zhí)行「數(shù)據(jù)淘汰策略」。
三、Redis 數(shù)據(jù)淘汰策略(內(nèi)存滿時騰空間)
當 Redis 內(nèi)存使用達到 maxmemory,且刪除所有過期 key 后內(nèi)存仍然不足時,就會觸發(fā)「數(shù)據(jù)淘汰策略」——刪除部分非過期 key,為新數(shù)據(jù)騰出內(nèi)存。
Redis 提供了 8 種淘汰策略(Redis 6.0+ 版本),其中常用的有 6 種,可分為「三類」:按訪問頻率淘汰、按時間淘汰、按隨機淘汰。
先明確:淘汰策略的核心前提
- 淘汰范圍:默認只淘汰「設(shè)置了過期時間的 key」;若所有設(shè)置過期時間的 key 都被淘汰完,內(nèi)存仍不足,則會淘汰「未設(shè)置過期時間的 key」(除非配置了只淘汰過期 key)。
- 觸發(fā)時機:每次執(zhí)行「寫操作」(set、hset、lpush 等)時,都會檢查內(nèi)存是否達到 maxmemory;若達到,則執(zhí)行淘汰策略,直到內(nèi)存低于 maxmemory,再執(zhí)行寫操作。
- 核心配置:通過
maxmemory-policy配置淘汰策略(默認策略:noeviction)。
8種淘汰策略詳解(按常用程度排序)
先給出所有策略的對照表,再逐一拆解常用策略:
淘汰策略(配置值) | 核心邏輯 | 適用場景 | 是否常用 |
|---|---|---|---|
allkeys-lru | 淘汰所有 key 中「最近最少使用」的 key(LRU:Least Recently Used) | 通用場景,大多數(shù)業(yè)務(wù)(如緩存、會話存儲) | ? 非常常用 |
volatile-lru | 只淘汰「設(shè)置了過期時間」的 key 中,最近最少使用的 key | 需要保留未過期 key(如核心配置),只淘汰臨時緩存 | ? 常用 |
allkeys-random | 隨機淘汰所有 key 中的任意一個 | 對 key 訪問頻率無要求,追求簡單高效 | ? 不常用 |
volatile-random | 只隨機淘汰「設(shè)置了過期時間」的 key | 同上,且需要保留未過期 key | ? 不常用 |
volatile-ttl | 只淘汰「設(shè)置了過期時間」的 key 中,剩余過期時間最短(ttl 最小)的 key | 希望盡快淘汰即將過期的臨時緩存 | ?? 場景化常用 |
volatile-lfu | 只淘汰「設(shè)置了過期時間」的 key 中,最不經(jīng)常使用的 key(LFU:Least Frequently Used) | key 訪問頻率差異大,優(yōu)先保留高頻訪問 key | ? 常用(Redis 4.0+ 支持) |
allkeys-lfu | 淘汰所有 key 中,最不經(jīng)常使用的 key | 通用場景,比 LRU 更精準(優(yōu)先淘汰低頻訪問 key) | ? 常用(Redis 4.0+ 支持) |
noeviction(默認) | 不淘汰任何 key,拒絕所有寫操作,返回錯誤(讀操作正常) | 不允許數(shù)據(jù)丟失的場景(如核心業(yè)務(wù)數(shù)據(jù)存儲) | ?? 特殊場景使用 |
重點拆解:常用策略的核心區(qū)別
日常開發(fā)中,最常用的是 allkeys-lru、volatile-lru、allkeys-lfu、volatile-lfu,這四個策略的核心區(qū)別的是「淘汰范圍」和「淘汰依據(jù)」:
1. LRU vs LFU:淘汰依據(jù)的區(qū)別
- LRU(最近最少使用):判斷標準是「最后一次訪問時間」—— 很久沒被訪問的 key,優(yōu)先淘汰。
- LFU(最不經(jīng)常使用):判斷標準是「一段時間內(nèi)的訪問次數(shù)」—— 訪問頻率最低的 key,優(yōu)先淘汰。
舉個例子:
- keyA:每天訪問 1 次,但每次訪問都是最近 1 小時內(nèi);
- keyB:每天訪問 100 次,但最后一次訪問是 3 天前。
LRU 會淘汰 keyB(最近最少訪問),LFU 會淘汰 keyA(訪問頻率最低)—— 可見 LFU 更適合「訪問頻率差異大」的場景,能更好地保留高頻訪問的核心緩存。
2. allkeys vs volatile:淘汰范圍的區(qū)別
- allkeys-*:淘汰范圍是「所有 key」(無論是否設(shè)置過期時間),適合「所有數(shù)據(jù)都是緩存」的場景(如商品緩存、接口緩存)。
- volatile-*:淘汰范圍是「只設(shè)置了過期時間的 key」,適合「有核心數(shù)據(jù)(未設(shè)置過期時間)和臨時緩存(設(shè)置過期時間)」的場景(如核心配置 key 不設(shè)置過期,臨時會話 key 設(shè)置過期)。
淘汰策略的底層實現(xiàn)(簡化版)
很多人好奇:Redis 是如何記錄 key 的訪問時間/頻率,實現(xiàn) LRU/LFU 淘汰的?這里給出簡化版原理,不用深入源碼,理解即可:
- 對于 LRU:Redis 給每個 key 維護一個「最后訪問時間戳」,淘汰時,遍歷候選 key(根據(jù)淘汰范圍),篩選出時間戳最小(最近最少訪問)的 key 進行刪除。
- 對于 LFU:Redis 給每個 key 維護一個「訪問計數(shù)器」,每次訪問 key 時,計數(shù)器加 1;每隔一段時間,計數(shù)器會衰減(避免舊的高頻 key 一直占用),淘汰時,篩選出計數(shù)器最?。ㄗ畈唤?jīng)常使用)的 key 進行刪除。
注意:Redis 的 LRU/LFU 并非「嚴格意義上的全量排序」(全量排序會消耗大量 CPU),而是通過「采樣排序」實現(xiàn)——每次淘汰時,隨機抽取一定數(shù)量的 key(默認 5 個,可通過 maxmemory-samples 配置),在采樣的 key 中選擇最該淘汰的,兼顧性能和準確性。
四、核心配置實戰(zhàn)(生產(chǎn)環(huán)境必看)
了解了刪除和淘汰策略后,最關(guān)鍵的是「生產(chǎn)環(huán)境如何配置」,避免內(nèi)存溢出或數(shù)據(jù)異常。以下是核心配置項和推薦配置:
1. 核心配置項說明
配置項 | 作用 | 推薦值 |
|---|---|---|
maxmemory | 設(shè)置 Redis 最大可用內(nèi)存(必須配置,否則內(nèi)存會無限增長,導(dǎo)致服務(wù)器內(nèi)存溢出) | 根據(jù)服務(wù)器內(nèi)存配置,建議設(shè)置為服務(wù)器內(nèi)存的 50%-70%(如 8G 內(nèi)存,設(shè)置為 4G) |
maxmemory-policy | 設(shè)置數(shù)據(jù)淘汰策略 | 通用場景:allkeys-lfu;有核心未過期 key:volatile-lfu |
hz | 定期刪除的頻率(每秒執(zhí)行次數(shù)) | 默認 10,內(nèi)存壓力大時可調(diào)整為 20 |
maxmemory-samples | LRU/LFU 淘汰時的采樣數(shù)量 | 默認 5,采樣數(shù)量越多,淘汰越精準,但 CPU 占用越高(建議保持默認) |
2. 推薦配置示例(redis.conf)
# 設(shè)置最大內(nèi)存為 4G maxmemory 4gb # 淘汰策略:所有 key 中最不經(jīng)常使用的 maxmemory-policy allkeys-lfu # 定期刪除頻率:每秒 10 次 hz 10 # LFU 采樣數(shù)量:5 個 maxmemory-samples 5
3. 動態(tài)調(diào)整配置(無需重啟Redis)
生產(chǎn)環(huán)境中,若需臨時調(diào)整配置,可通過 Redis 命令動態(tài)修改(重啟后失效,需同步修改 redis.conf 永久生效):
# 動態(tài)設(shè)置最大內(nèi)存為 4G config set maxmemory 4gb # 動態(tài)設(shè)置淘汰策略為 allkeys-lfu config set maxmemory-policy allkeys-lfu # 查看當前所有配置 config get *
五、常見問題與避坑指南
在使用 Redis 數(shù)據(jù)刪除與淘汰策略時,很多開發(fā)者會遇到以下問題,提前規(guī)避能少走很多彎路:
1. 問題1:內(nèi)存滿了,Redis 拒絕寫操作(返回 OOM command not allowed when used memory > 'maxmemory')
原因:淘汰策略設(shè)置為默認的 noeviction,內(nèi)存滿時不淘汰任何 key,拒絕所有寫操作。
解決方案:將淘汰策略修改為 allkeys-lfu 或 volatile-lfu,同時檢查 maxmemory 是否配置合理。
2. 問題2:大量過期 key 堆積,內(nèi)存占用過高
原因:定期刪除頻率過低(hz 太小),且過期 key 長期不被訪問(惰性刪除無法觸發(fā))。
解決方案:適當提高 hz 值(如調(diào)整為 20),同時在業(yè)務(wù)層定期清理過期 key(如通過定時任務(wù)執(zhí)行 DEL 命令)。
3. 問題3:核心 key 被淘汰
原因:淘汰策略設(shè)置為 allkeys-*,核心 key 未設(shè)置過期時間,但內(nèi)存滿時被淘汰;或核心 key 設(shè)置了過期時間,被 volatile-* 策略淘汰。
解決方案:核心 key 不設(shè)置過期時間,淘汰策略使用 volatile-lfu(只淘汰設(shè)置了過期時間的臨時 key)。
4. 問題4:LRU 淘汰策略不精準
原因:maxmemory-samples 采樣數(shù)量太少,導(dǎo)致篩選出的“最近最少使用”key 不是真正的低頻 key。
解決方案:適當提高 maxmemory-samples(如調(diào)整為 10),但需注意 CPU 負載。
六、總結(jié)
Redis 數(shù)據(jù)刪除與淘汰策略,核心是「平衡 CPU 性能、內(nèi)存利用率和數(shù)據(jù)一致性」,記住以下核心要點,就能輕松應(yīng)對生產(chǎn)場景:
- 「刪除策略」是清理過期 key,三種結(jié)合:惰性刪除(省 CPU)+ 定期刪除(折中)+ 主動刪除(內(nèi)存不足時);
- 「淘汰策略」是內(nèi)存滿時騰空間,常用 allkeys-lfu(通用)和 volatile-lfu(有核心 key);
- 生產(chǎn)環(huán)境必須配置 maxmemory 和 maxmemory-policy,避免內(nèi)存溢出;
- LRU 看“最近訪問時間”,LFU 看“訪問頻率”,根據(jù)業(yè)務(wù)場景選擇;
- 核心 key 不設(shè)置過期時間,避免被淘汰。
理解了這些策略,不僅能解決 Redis 內(nèi)存相關(guān)的問題,還能在面試中從容應(yīng)對相關(guān)問題(Redis 淘汰策略是后端面試高頻題)。
如果需要,我還可以為你補充:
- LRU/LFU 底層源碼簡化解析;
- 過期 key 清理的監(jiān)控方法;
- 不同業(yè)務(wù)場景(緩存、會話、配置存儲)的具體策略配置。
到此這篇關(guān)于Redis數(shù)據(jù)刪除與淘汰策略從原理到實戰(zhàn)指南的文章就介紹到這了,更多相關(guān)Redis數(shù)據(jù)刪除與淘汰策略內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Redis官方可視化工具RedisInsight的安裝使用詳細教程(功能強大)
RedisInsight是Redis官方出品的可視化管理工具,可用于設(shè)計、開發(fā)、優(yōu)化你的Redis應(yīng)用。支持深色和淺色兩種主題,界面非常炫酷,接下來通過本文給大家介紹Redis官方可視化工具RedisInsight的安裝使用過程,需要的朋友可以參考下2022-04-04
使用lua+redis解決發(fā)多張券的并發(fā)問題
這篇文章主要介紹了使用lua+redis解決發(fā)多張券的并發(fā)問題,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-01-01

