Redis過期數(shù)據(jù)清理的策略實戰(zhàn)
一句話真相:Redis的過期清理就像"超市臨期商品管理"——惰性刪除是顧客結(jié)賬時檢查保質(zhì)期,定期刪除是店員定時巡檢貨架!
一、為什么需要數(shù)據(jù)過期?內(nèi)存管理的生死線
真實案例:某社交App因未設(shè)過期時間,3000萬用戶會話數(shù)據(jù)永久堆積,導(dǎo)致:
- 內(nèi)存爆滿,服務(wù)崩潰
- 從Redis恢復(fù)數(shù)據(jù)耗時3小時
- 直接損失800萬訂單!
Redis內(nèi)存警告:
127.0.0.1:6379> info memory used_memory_human:6.0G # 內(nèi)存使用量 maxmemory_human:8.0G # 內(nèi)存上限 mem_fragmentation_ratio:1.8 # 碎片率過高!
二、過期策略雙核心:惰性刪除 + 定期刪除
| 策略 | 觸發(fā)時機 | 優(yōu)點 | 缺點 |
|---|---|---|---|
| 惰性刪除 | 訪問Key時檢查 | 零額外CPU消耗 | 冷數(shù)據(jù)長期不釋放 |
| 定期刪除 | 定時隨機掃描 | 主動釋放內(nèi)存 | 可能短時阻塞 |

三、惰性刪除:精準(zhǔn)狙擊的"特工"
1. 執(zhí)行流程
2. 源碼實現(xiàn)(C語言偽代碼)
int expireIfNeeded(redisDb *db, robj *key) {
if (!keyIsExpired(db,key)) return 0; // 未過期
deleteKey(db,key); // 執(zhí)行刪除
return 1;
}
robj *lookupKeyRead(redisDb *db, robj *key) {
if (expireIfNeeded(db,key) == 1) { // 檢查過期
return NULL; // 已刪除返回空
}
return lookupKey(db,key);
}
3. 實戰(zhàn)風(fēng)險:僵尸Key問題
場景:
# 大量已過期但永不訪問的Key SET access_log:20230101 "big_data" EX 86400
后果:內(nèi)存被無形占用,可用空間持續(xù)減少!
四、定期刪除:主動出擊的"巡邏隊"
1. 三層漸進式掃描

2. 核心算法參數(shù)
// redis.conf 配置 hz 10 // 每秒執(zhí)行10次定期刪除(默認(rèn)) // 源碼參數(shù) #define ACTIVE_EXPIRE_CYCLE_KEYS_PER_LOOP 20 // 每次掃描20個key #define ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC 25 // CPU占用≤25%
3. 性能優(yōu)化:自適應(yīng)掃描
- CPU空閑時:增加掃描頻次(
hz 100) - 內(nèi)存緊張時:每次掃描更多Key(可調(diào)參)
五、內(nèi)存耗盡時的最后防線:淘汰策略
當(dāng)內(nèi)存超maxmemory時觸發(fā):
| 策略 | 機制 | 適用場景 |
|---|---|---|
| volatile-lru(默認(rèn)) | 淘汰最近最少使用的過期Key | 緩存場景 |
| allkeys-lru | 淘汰所有Key中的LRU | 內(nèi)存不足時優(yōu)先選擇 |
| volatile-ttl | 淘汰剩余生存時間最短的Key | 時效性敏感數(shù)據(jù) |
| noeviction | 拒絕寫入并報錯 | 關(guān)鍵數(shù)據(jù)不允許丟失 |
配置方式:
# redis.conf maxmemory 8gb maxmemory-policy volatile-lru
六、四大實戰(zhàn)陷阱與解決方案
陷阱1:過期Key集中導(dǎo)致雪崩
場景:
# 同一秒設(shè)置大量Key過期 SET key1 value EX 3600 SET key2 value EX 3600 # 同時設(shè)置100萬Key
后果:3600秒后同時過期 → 定期刪除壓力暴增!
解決方案:
# 添加隨機過期時間偏移 expire_time = 3600 + random.randint(0, 600) # 增加0-10分鐘隨機值 redis.setex(key, expire_time, value)
陷阱2:大Key刪除阻塞服務(wù)
案例:刪除10MB的Hash Key耗時150ms → 阻塞其他請求!
優(yōu)化方案:
# 異步刪除(Redis 4.0+) UNLINK big_key # 非阻塞刪除 # 分批次刪除 HSCAN big_key 0 COUNT 100 # 分批遍歷 HDEL big_key field1 field2 ... # 分批刪除
陷阱3:主從不一致
問題:主庫刪除過期Key后,從庫可能未同步刪除
解決方案:
# 開啟從庫主動檢測(Redis 3.2+) replica-serve-stale-data no
陷阱4:持久化導(dǎo)致過期復(fù)活
原理:RDB快照中的過期Key重啟后重新加載
規(guī)避方法:
# 啟用AOF重寫時主動刪除過期Key aof-rewrite-incremental-fsync yes
七、最佳配置指南
1. 生產(chǎn)環(huán)境推薦配置
# 內(nèi)存上限(物理內(nèi)存70%) maxmemory 16gb # 淘汰策略(緩存場景) maxmemory-policy volatile-lru # 定期刪除頻率 hz 10 # 開啟異步刪除 lazyfree-lazy-eviction yes
2. 監(jiān)控命令大全
# 查看過期Key數(shù)量 redis-cli info | grep expired_keys # 內(nèi)存碎片率 redis-cli info | grep mem_fragmentation_ratio # 實時監(jiān)控淘汰情況 redis-cli --stat
八、總結(jié):Redis過期數(shù)據(jù)清理三原則
- 雙重保障:
- 訪問時檢查(惰性刪除)
- 定時主動掃描(定期刪除)
- 淘汰兜底:內(nèi)存不足時按策略清理
- 避坑關(guān)鍵:
- 分散過期時間
- 大Key異步刪除
- 監(jiān)控碎片率

黃金口訣:
- 冷門數(shù)據(jù)靠定期掃
- 熱點訪問惰性刪
- 內(nèi)存爆炸淘汰保
以上就是Redis過期數(shù)據(jù)清理的策略實戰(zhàn)的詳細(xì)內(nèi)容,更多關(guān)于Redis過期數(shù)據(jù)清理的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Redis遍歷所有key的兩個命令(KEYS 和 SCAN)
這篇文章主要介紹了Redis遍歷所有key的兩個命令(KEYS 和 SCAN),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04
關(guān)于在Redis中使用Pipelining加速查詢的問題
這篇文章主要介紹了在Redis中使用Pipelining加速查詢,Redis是一個client-server模式的TCP服務(wù),也被稱為Request/Response協(xié)議的實現(xiàn),本文通過一個例子給大家詳細(xì)介紹,感興趣的朋友一起看看吧2022-05-05
Spring?Boot實戰(zhàn)解決高并發(fā)數(shù)據(jù)入庫之?Redis?緩存+MySQL?批量入庫問題
這篇文章主要介紹了Spring?Boot實戰(zhàn)解決高并發(fā)數(shù)據(jù)入庫之?Redis?緩存+MySQL?批量入庫問題,本文通過圖文實例相結(jié)合給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-02-02
一次關(guān)于Redis內(nèi)存詭異增長的排查過程實戰(zhàn)記錄
這篇文章主要給大家分享了一次關(guān)于Redis內(nèi)存詭異增長的排查過程實戰(zhàn)記錄,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Redis具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-07-07

