LRU 相关知识
一、什么是缓存?
缓存是一种“临时存储数据的技术”,目的是加快数据访问速度。
比如我们浏览网页时,浏览器会把图片、文字等临时存在本地(缓存),下次再打开同一网页时,不用重新从服务器下载,直接从缓存读取,速度更快。
缓存的容量是有限的(比如浏览器缓存不能无限大),当缓存存满时,需要“淘汰”一部分旧数据,腾出空间给新数据。而“淘汰策略”不同,就产生了不同类型的缓存。
二、什么是 LRU 缓存?
LRU 是“Least Recently Used”的缩写,意思是“最近最少使用”。
LRU 缓存的核心思想是:当缓存满了之后,会优先淘汰“最近最少被使用”的数据,留下“最近经常被使用”的数据。
举个例子:
假设缓存容量为 3(最多存 3 条数据),我们按以下顺序访问数据:
- 访问 A → 缓存内容:[A](A 是最近使用的)
- 访问 B → 缓存内容:[A,B](B 是最近使用的)
- 访问 C → 缓存内容:[A,B,C](C 是最近使用的,缓存满了)
- 访问 B → B 被重新使用,变成最近使用的 → 缓存内容:[A,C,B](B 移到“最近”)
- 访问 D → 缓存满了,需要淘汰“最近最少使用”的数据。此时最近使用顺序是:B(最近)、C、A(最久没被用)→ 淘汰 A,存入 D → 缓存内容:[C,B,D]
三、其他常见的缓存类型(按淘汰策略分类)
除了 LRU,还有很多基于不同淘汰策略的缓存类型,适用于不同场景:
1. FIFO 缓存(先进先出)
- 全称:First In First Out(先进先出)。
- 核心思想:按“数据进入缓存的顺序”淘汰,最早进入的先被淘汰,和使用频率无关。
- 例子:缓存容量 3,依次存入 A、B、C,再存入 D 时,淘汰最早的 A。
- 适用场景:数据访问顺序固定(比如日志数据按时间顺序访问),但对“常用数据”不友好(如果早期存入的是高频数据,也会被淘汰)。
2. LFU 缓存(最不经常使用)
- 全称:Least Frequently Used(最不经常使用)。
- 核心思想:按“数据被使用的总次数”淘汰,使用次数最少的先被淘汰。
- 例子:缓存中 A 被用了 2 次,B 被用了 5 次,C 被用了 1 次,满了之后存入 D,会淘汰使用次数最少的 C。
- 适用场景:数据的“使用频率”相对固定(比如某些高频访问的配置数据),但对“新数据”不友好(新数据使用次数少,容易被淘汰)。
3. TTL 缓存(存活时间)
- 全称:Time To Live(存活时间)。
- 核心思想:不给数据“使用频率”排序,而是给每个数据设置一个“过期时间”,到期后自动淘汰,不管是否被使用过。
- 例子:浏览器缓存的临时文件可能设置 1 小时过期,过期后重新从服务器获取。
- 适用场景:数据有“时效性”(比如新闻、验证码、会话信息),过期后数据会失效。
4. ARC 缓存(自适应替换缓存)
- 全称:Adaptive Replacement Cache(自适应替换)。
- 核心思想:结合了 LRU 和 LFU 的优点,会动态学习数据的访问模式,自动调整“最近使用”和“频繁使用”数据的淘汰优先级,命中率更高。
- 适用场景:对缓存命中率要求高的复杂场景(比如数据库缓存),但实现较复杂。
5. LIRS 缓存(低交互率最近使用)
- 全称:Low Inter-reference Recency Set(低交互率最近使用)。
- 核心思想:不仅关注“最近使用”,还关注“两次访问的间隔时间”,优先淘汰那些“访问间隔长、且最近少用”的数据,适合处理“突发访问”场景。
总结
不同缓存类型的核心区别在于“满了之后淘汰谁”:
- LRU:淘汰“最近最少用”的(适合热点数据经常变化的场景);
- FIFO:淘汰“最早进”的(简单但命中率低);
- LFU:淘汰“用得最少”的(适合频率固定的高频数据);
- TTL:淘汰“过期”的(适合时效性数据)。
实际开发中,LRU 因为实现相对简单且命中率较高,是最常用的缓存类型之一(比如 Redis 的过期策略就支持 LRU)。