LRU 缓存淘汰策略
1、基本介绍
-
LRU,全称 Least Recently Used,即最近最少使用,它是一种经典的缓存淘汰策略
-
当缓存空间满了,需要腾出位置放新数据时,LRU 会优先淘汰那个最久没有被访问过的数据
-
LRU 通常需要支持如下两种操作,且要求高效,一般是 O(1) 时间复杂度
访问数据(get)
如果数据在缓存中,把它标记为最近使用,并移到最前面 如果不在,返回空插入数据(put)
如果数据已存在,更新值并移到最前面 如果不存在,插入到最前面 如果插入后超出容量,删除最后面(最久未使用)的那个数据 -
为了在 O(1) 时间内完成查找、插入和删除,LRU 通常结合如下两种数据结构
哈希表:实现 O(1) 的快速查找,判断某个 key 是否在缓存中
双向链表:维护访问顺序。链表头部是最近使用的,尾部是最久未使用的。因为需要频繁移动节点,所以用双向链表而不是单链表
2、举例说明
- 假设缓存容量为 3
-
访问 A → 缓存:
[A] -
访问 B → 缓存:
[B, A] -
访问 C → 缓存:
[C, B, A] -
访问 A → A 被移到最前 → 缓存:
[A, C, B] -
插入 D → 容量满了,淘汰最久未使用的 B → 缓存:
[D, A, C]
3、应用场景
-
CPU 缓存:利用局部性原理,保留最近使用的内存块
-
数据库缓冲池:例如,MySQL 的 InnoDB 缓冲池,用 LRU 的变体来管理内存页
-
操作系统页面置换:决定哪些内存页可以被换出
-
Redis:作为缓存淘汰策略之一
-
浏览器 / HTTP 缓存:决定哪些资源保留在本地
4、优缺点
(1)优点
-
实现相对简单,命中率在多数场景下表现不错
-
符合最近使用过的东西更可能被再次使用的直觉
(2)缺点
-
对偶发性的批量操作不友好。例如,一次性扫描大量数据,会把原本的热点数据全部挤出去,导致缓存命中率骤降。这被称为缓存污染
-
实际系统中常用改进版,例如,LRU-K、2Q、LFU 等