| 策略 | 原理 | 優點 | 缺點 | 採用者 |
|---|---|---|---|---|
| 定時刪除 | 設定定時器,到期精確刪除 | 記憶體釋放最及時 | CPU 佔用高、定時器開銷大、高併發下性能崩潰 | 無 |
| 惰性刪除 | 讀取時檢查過期,過期則刪除 | CPU 友好、只處理必要鍵 | 記憶體洩漏風險:冷鍵長期佔用 | Memcached |
| 定期刪除 | 周期性隨機抽樣檢查並刪除 | 平衡 CPU 與記憶體、可控頻率 | 參數調優難度大、不如定時刪除即時 | Redis (配合惰性) |
所有讀寫命令執行前調用 expireIfNeeded(key):
// 核心邏輯
if (key.expireTime != -1 && key.expireTime < currentTimeMillis()) {
deleteKey(key);
return null; // 命中過期鍵視同不存在
}
特別注意:SETNX 等寫命令也會觸發檢查,避免過期鍵阻礙新值寫入。
核心函數 activeExpireCycle(),由 serverCron() 定時觸發 (預設 10Hz):
void activeExpireCycle() {
for (int db = currentDb; ; db = (db + 1) % server.dbnum) {
if (db == currentDb && loopCount > 0) break; // 掃描完一輪退出
dict *expires = server.db[db].expires;
if (dictSize(expires) == 0) continue; // 無過期鍵跳過
for (int i = 0; i < 20; i++) { // 每庫固定抽樣 20 個
if (dictSize(expires) == 0) break;
key = dictGetRandomKey(expires);
if (key.expireTime < now) deleteKey(key);
}
if (timeSpent > TIME_LIMIT) break; // 保護 CPU 時間片
}
currentDb = db; // 記錄下輪起始庫
}
hz 10:serverCron 執行頻率 (Hz),影響定期刪除頻率ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 20:每庫每輪抽樣數ACTIVE_EXPIRE_CYCLE_TIME_LIMIT:單輪 CPU 時間上限 (預設 25% CPU 時間片)| 模式 | RDB | AOF |
|---|---|---|
| 過期鍵 | 不寫入快照 | 不寫入 AOF;主動刪除時追加 DEL 指令 |
| 主從同步 | 從節點載入 RDB 時自動過濾 | 主節點 DEL 指令同步到從節點 |
Memcached 僅採用惰性刪除,Redis 雙策略在記憶體效率與 CPU 佔用間取得更好平衡,是 Redis 適合作為高效能緩存的關鍵原因之一。