背景
最近没事看公司自研ssr框架feb,注意到里面页面级缓存和组件级缓存用到了LRU缓存,这让我想起了之前看keep-alive源码,貌似也是使用了LRU缓存。之前看过redis的文章,好像也是基于这个理念实现的;在刷leetcode的时候,有时候也会碰到类似LRU的题目。今天记录一下LRU算法,加深我们对这块的印象。
研究
LRU (Least recently used :最近最少使用)最近被访问的,被访问的几率变大。最少被访问的,当磁盘被写满时,会被清除。
一张图来理解一下:
- 假设我们有一块内存,一共能够存储 5 数据块;
- 依次向内存存入A、B、C、D、E,此时内存已经存满;
- 再次插入新的数据时,会将在内存存放时间最久的数据A淘汰掉;
- 当我们在外部再次读取数据B时,已经处于末尾的B会被标记为活跃状态,提到头部,数据C就变成了存放时间最久的数据;
- 再次插入新的数据G,存放时间最久的数据C就会被淘汰掉;
算法实现
class LRUCache {
// 存储数据
put (key, value) {
if (this.cache[key]) {
// 如果该 key 之前存在,将 key 重新激活
this.active(key)
this.cache[key] = value
// 而且此时缓存的长度不会发生变化
// 所以不需要进行后续的长度判断,可以直接返回
return
}
?
// 存储之前需要先判断长度是否达到上限
if (this.list.length >= this.capacity) {
// 由于每次存储后,都会将 key 放入 list 最后,
// 所以,需要取出第一个 key,并删除cache中的数据。
const latest = this.list.shift()
delete this.cache[latest]
}
// 写入缓存
this.cache[key] = value
// 写入缓存后,需要将 key 放入 list 的最后
this.list.push(key)
}
}
|