Redis的LFU(Least Frequently Used)策略通過動態跟蹤鍵的訪問頻率實現淘汰決策,其核心工作邏輯可分為以下四個部分:
- 數據結構設計?
字段拆分?:每個Redis對象(redisObject)的lru字段(24位)被拆分為兩部分:
高16位(ldt)?:記錄最后一次訪問的時間戳(精度為秒),用于計算訪問間隔和頻率衰減。
低8位(logc)?:邏輯計數器,初始值為5,表示訪問頻率的近似值,值越低越可能被淘汰。 - 訪問頻率衰減機制?
動態衰減邏輯?:每次訪問鍵時,根據當前時間與ldt的差值計算logc的衰減量:
時間間隔越大,衰減幅度越大(如長時間未訪問的鍵,logc顯著降低)。
衰減公式:logc = logc - (當前時間 - ldt) * 衰減系數(默認衰減系數為1)。
目的?:避免歷史高頻但近期不再使用的鍵長期駐留內存。 - 訪問頻率更新策略?
概率性增加?:在衰減后,logc的值通過概率算法更新:
計數器越高,進一步增加的概率越低(如logc=10時,增加概率為1/(10+1)=9.1%)。
計算公式:p = 1.0 / (logc_current * lfu_log_factor + 1)(lfu_log_factor默認為10)。
目的?:防止短暫突發訪問導致logc快速膨脹,確保長期高頻訪問的鍵才具有高優先級。 - 淘汰執行流程?
內存監控?:Redis每秒檢查10次內存使用情況,觸發淘汰的條件為內存超過maxmemory閾值。
候選集篩選?:根據策略(如volatile-lfu或allkeys-lfu),從對應鍵空間中隨機抽樣maxmemory-samples個鍵(默認5個)。
淘汰決策?:選擇抽樣中logc值最小的鍵;若logc相同,則比較ldt時間戳(更早未被訪問的鍵優先淘汰)。
配置參數?
lfu-log-factor?:控制logc增長的難度(值越大,增長越慢)。
lfu-decay-time?:定義衰減時間窗口(單位:分鐘),默認1分鐘觸發一次衰減計算。
通過以上機制,Redis的LFU在有限內存和計算開銷下,實現了對高頻訪問鍵的高效保留,同時避免傳統LFU算法的內存與性能瓶頸。