文章目录
近期文章:
- 从底层视角看requestAnimationFrame的性能增强
- Nginx Upstream了解一下
- 实现篇:一文搞懂Promise是如何实现的
- 实现篇:如何手动实现JSON.parse
- 实现篇:如何亲手定制实现JSON.stringify
- 一文搞懂 Markdown 文档规则
1 什么是LRU
LRU(Least Recently Used,最近最少使用)是一种缓存淘汰策略,核心思想是优先淘汰最久未被访问的数据,适用于有限容量的缓存场景。其运作逻辑基于时间局部性原理,即最近被访问的数据很可能在短期内再次被访问。
LRU的常见应用场景
- 前端领域
- 浏览器缓存:存储最近访问的网页资源(如图片、CSS/JS文件)
- SPA应用状态管理:缓存高频访问的API响应数据,减少网络请求
- 路由缓存:Vue/React中保留最近访问的组件实例,加速页面切换
- 后端与系统层
- 数据库查询缓存:如MySQL/Redis的缓冲池管理
- 操作系统内存管理:虚拟内存的页面置换(如Linux内核的
swap
机制) - CDN节点缓存:优化热门资源的分发效率
- 通用缓存优化
- API网关:缓存高频接口响应,降低后端压力
- 计算密集型任务:缓存中间计算结果(如斐波那契数列、图像处理)
2 JavaScript实现
2.1 基于Map
的简洁实现
利用Map
数据结构保持键值对的插入顺序,结合其原生方法实现高效操作,相关示例代码:js-code/LRU
特点:
- 通过
Map
的插入顺序自动维护访问时间顺序 get
和put
操作均保持O(1)时间复杂度- 代码简洁,适用于中小规模缓存场景
实现代码:
class LRUCache {
constructor(capacity) {
this.capacity = capacity; // 缓存容量
this.cache = new Map(); // 存储键值对
}
get(key) {
if (!this.cache.has(key)) return -1;
const value = this.cache.get(key);
this.cache.delete(key); // 删除旧键
this.cache.set(key, value); // 重新插入以更新顺序
return value;
}
put(key, value) {
if (this.cache.has(key)) {
this.cache.delete(key);
} else if (this.cache.size >= this.capacity) {
// 删除最久未使用的键(Map的keys().next().value返回第一个键)
this.cache.delete(this.cache.keys().next().value);
}
this.cache.set(key, value);
}
}
使用示例:
const lru = new LRUCache(3);
lru.put('A', 1); // 缓存: A(1)
lru.put('B', 2); // 缓存: B(2) → A(1)
lru.put('C', 3); // 缓存: C(3) → B(2) → A(1)
console.log(lru.get('A')); // 输出1 → 缓存变为A(1) → C(3) → B(2)
lru.put('D', 4); // 淘汰B → 缓存: D(4) → A(1) → C(3)
console.log(lru.get('B')); // 输出-1(已被淘汰)
2.2 双向链表+哈希表的高性能实现
针对大规模数据场景,采用双向链表维护访问顺序,哈希表提供快速查找
优势:
- 链表