缓存数据淘汰算法LRU 和 LFU

本文由 AI 生成,内容仅供参考,请仔细甄别。


一、什么是缓存淘汰算法?

缓存空间是有限的,当缓存已满又需要新增数据时,需要一个策略决定“谁被淘汰(evict)”。


二、LRU(最近最少使用)

📌 全称:Least Recently Used

📘 核心思想:

最近最少使用的数据优先被淘汰

也就是说,很久没被访问的数据会被认为“不重要”,优先移除。

📈 应用场景:

  • 适合访问具有时间局部性的场景(最近访问过的数据还可能被再次访问)
  • 常见于:Redis 默认淘汰策略、操作系统页面置换(如 Linux 的 page cache)

🛠️ 实现方式:

  • 通常用 双向链表 + HashMap
  • Java 中:LinkedHashMap 就可以实现 LRU 缓存
  • 现代高性能实现(如 Caffeine)使用 分段队列 + 时间窗口优化

✅ 优点:

  • 简单、高效
  • 适用于大多数缓存场景

❌ 缺点:

  • 无法区分访问频率 → 可能会淘汰热点但“间隔长”的数据

三、LFU(最不经常使用)

📌 全称:Least Frequently Used

📘 核心思想:

访问次数最少的数据优先被淘汰

也就是说,“用得不多”的数据会被优先淘汰,哪怕它刚刚访问过。

📈 应用场景:

  • 数据访问具有 频率热点特征 的场景(如部分热门商品/文章访问次数远高于其他)
  • 比如新闻首页最热榜、搜索缓存等

🛠️ 实现方式:

  • 常用结构:最小堆 + HashMap
  • 或:频率分桶法(frequency-bucket + 双链表)
  • Java 高性能实现:Caffeine 支持近似 LFU

✅ 优点:

  • 保留使用频率高的数据,更适合“冷数据很多”的场景

❌ 缺点:

  • 实现复杂
  • 频率需要定期衰减(否则冷数据可能因早期频繁访问而“常驻”)

四、LRU vs LFU 对比总结

特性 LRU LFU
策略核心 最近最少使用 最少访问次数
关注点 时间顺序 访问频率
数据保留倾向 最近用过的数据 访问次数多的数据
热点识别能力 一般(只看是否“最近”) 强(会识别长期热点)
实现复杂度 简单(双向链表 + HashMap) 复杂(频率桶 + HashMap + 最小堆等)
适合场景 普通缓存、短期热点 长期热点识别、高性能缓存(如 Caffeine)

五、简单代码对比(Java 示例)

🔹 LRU 简单实现(基于 LinkedHashMap):

class LRUCache<K, V> extends LinkedHashMap<K, V> {
    private final int capacity;

    public LRUCache(int capacity) {
        super(capacity, 0.75f, true); // accessOrder = true 实现 LRU
        this.capacity = capacity;
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        return size() > capacity;
    }
}

🔸 LFU 实现略复杂,推荐使用开源工具:

  • Caffeine(支持 LRU + LFU 的现代 Java 缓存框架)
  • Redis:从 Redis 4.0 开始支持 LFU 模式(需配置 maxmemory-policyallkeys-lfu

六、扩展:其他常见缓存策略

策略名 全称 简要说明
FIFO First In First Out 最先加入的先被淘汰(简单但容易误判重要数据)
ARC Adaptive Replacement Cache 综合 LRU 和 LFU,自适应调整
Random 随机淘汰 Redis 支持,适用于极端高性能要求场景

七、总结

  • 如果你希望缓存保留 “最近使用过” 的数据:选 LRU
  • 如果你希望缓存保留 “访问频率高” 的数据:选 LFU
  • 如果对命中率要求更高,建议用现代实现(如 Caffeine,它做了 LRU+LFU 混合优化)

posted @ 2025-06-05 22:05  MuXinu  阅读(194)  评论(0)    收藏  举报