---
# System prepended metadata

title: 27 | 緩存被汙染了，該怎麼辦？

---

# 27 | 緩存被汙染了，該怎麼辦？

## 緩存汙染

有些數據被訪問的次數非常少，甚至只會被訪問一次。當這些數據服務完訪問請求後，如果還繼續留存在緩存中的話，就只會白白佔用緩存空間。這種情況，就是緩存汙染。

## 如何解決緩存汙染問題？

分析前幾章提到的淘汰策略是否可以解決緩存污染

### volatile-random 和 allkeys-random 

效果非常有限

![CleanShot 2025-09-10 at 22.54.16@2x](https://hackmd.io/_uploads/S1tXbzysxg.jpg)

假設我們配置 Redis 緩存使用 allkeys-random 淘汰策略，當緩存寫滿時，allkeys-random 策略隨機選擇了數據 20 進行淘汰。不巧的是，數據 20 緊接著又被訪問了，此時，Redis 就會發生了緩存缺失，降低了應用的請求響應速度。

### volatile-ttl

效果非常有限

複習：針對的是設置了過期時間的數據，把這些數據中剩餘存活時間最短的篩選出來並淘汰掉。

剩餘存活時間並不能直接反映數據再次訪問的情況。所以，按照 volatile-ttl 策略淘汰數據，和按隨機方式淘汰數據類似，也可能出現數據被淘汰後，被再次訪問導致的緩存缺失問題。

### LRU 緩存策略

效果有限

複習：LRU 策略的核心思想：如果一個數據剛剛被訪問，那麼這個數據肯定是熱數據，還會被再次訪問。

在進行數據淘汰時，LRU 策略會在候選數據集中淘汰掉 lru 字段值最小的數據（也就是訪問時間最久的數據）。

![CleanShot 2025-09-10 at 22.58.02@2x](https://hackmd.io/_uploads/SJOZGGyjgg.jpg)

### LFU 緩存策略的優化

LFU 緩存策略是在 LRU 策略基礎上，為每個數據增加了一個計數器，來統計這個數據的訪問次數。
LFU 策略篩選淘汰數據時，首先會根據數據的訪問次數進行篩選，把訪問次數最低的數據淘汰出緩存。如果兩個數據的訪問次數相同，LFU 策略再比較這兩個數據的訪問時效性，把距離上一次訪問時間更久的數據淘汰出緩存。

Redis 在實現 LFU 策略的時候，只是把原來 24bit 大小的 lru 字段，又進一步拆分成了兩部分。

- ldt 值：lru 字段的前 16bit，表示數據的訪問時間戳；
- counter 值：lru 字段的後 8bit，表示數據的訪問次數。Redis 只使用了 8bit 記錄數據的訪問次數，而 8bit 記錄的最大值是 255

並不是數據被訪問一次 counter 值就會 +1

![CleanShot 2025-09-10 at 23.01.14@2x](https://hackmd.io/_uploads/HJF6MMJsgx.jpg)
一般可以將 lfu_log_factor 取值為 10

### LFU 衰減機制

Redis 在實現 LFU 策略時，還設計了一個 counter 值的衰減機制。LFU 策略使用衰減因子配置項 lfu_decay_time 來控制訪問次數的衰減

舉個例子，假設 lfu_decay_time 取值為 1，如果數據在 N 分鐘內沒有被訪問，那麼它的訪問次數就要減 N。如果 lfu_decay_time 取值更大，那麼相應的衰減值會變小，衰減效果也會減弱。所以，如果業務應用中有短時高頻訪問的數據的話，建議把 lfu_decay_time 值設置為 1，這樣一來，LFU 策略在它們不再被訪問後，會較快地衰減它們的訪問次數，儘早把它們從緩存中淘汰出去，避免緩存汙染。