目录
LRU介绍:
一些淘汰策略:
Java简单实现LRU:
测试:
编辑
实现原理:
LRU介绍:
LRU 是 "Least Recently Used" 的缩写,意为"最近最少使用"。它是计算机科学中的一种缓存淘汰策略,主要用于缓存内存管理。LRU 的原理是在缓存已满且需要添加新项时,从缓存中移除最近最少使用的项。
通常用于操作系统种内存页的置换,把不常用的放回外存,常用的放入内存,可以提高我们所需的数据在内存的命中率。
同时在redis中也会用到,redis是一种内存数据库,我们想要redis中存储我们的热点数据,就需要把一些不常用的数据替换掉,所以redis提供了多种的淘汰更新策略。
一些淘汰策略:
-
No Eviction (无淘汰): 当内存达到限制时,新写入操作会导致写入操作失败并返回错误。
-
All Keys Random (随机淘汰): Redis 会从所有的键中随机选择一个进行淘汰。
-
Volatitle Least Recently Used (Volatile-LRU): Redis 会从设置了过期时间的键中,选择最近最少使用的键进行淘汰。
-
Volatile Least Frequently Used (Volatile-LFU): Redis 会从设置了过期时间的键中,选择最不经常使用的键进行淘汰。
-
Volatile Random (Volatile-Random): Redis 会从设置了过期时间的键中随机选择一个进行淘汰。
-
Least Recently Used (LRU): Redis 会从所有的键中,选择最近最少使用的键进行淘汰。
-
Least Frequently Used (LFU): Redis 会从所有的键中,选择最不经常使用的键进行淘汰。
-
Random (随机): Redis 会从所有的键中随机选择一个进行淘汰。
在 Redis 中,可以通过配置 maxmemory-policy
参数来指定使用的淘汰策略。每种策略都有其适用的场景,选择合适的淘汰策略可以更好地管理内存和提高性能。
在一般情况下,用的最多的当然就是LRU最近最少使用, 因为最近被访问次数越多的数据,在未来被访问的概率会更高,我们无法预测未来发生什么,所以淘汰最近少使用的,正常都是相对较好的选择。
Java简单实现LRU:
class Memory {
private static PriorityQueue<Pair<Integer, Integer>> pq = new PriorityQueue<>((a, b) -> {
return a.getValue() - b.getValue();
}); // pair<key, count>
private static int size = 3;
public static void select(int key) {
System.out.println(key + "进行查询");
for (Pair<Integer, Integer> t: pq) {
if (t.getKey() == key) {
int nextCount = t.getValue() + 1;
pq.remove(t);
pq.offer(new Pair<>(t.getKey(), nextCount));
return;
}
}
pq.offer(new Pair<>(key, 1));
if (pq.size() > size) {
pq.poll();
}
}
public static void show() {
System.out.println(pq.toString());
}
}
测试:
public class Main {
public static void main(String[] args) {
Memory memory = new Memory();
Memory.select(1);
Memory.show();
Memory.select(2);
Memory.show();
Memory.select(1);
Memory.show();
Memory.select(3);
Memory.show();
Memory.select(4);
Memory.show();
Memory.select(3);
Memory.show();
Memory.select(5);
Memory.show();
}
}
实现原理:
我这里是用的一个优先级队列,也就是堆来实现,因为堆可以很好的进行排序,同时控制堆中的节点个数。
每个节点存储的一个pair对,key放的是元素,value则放的是该元素最近被使用的次数。排序就是利用value来进行的。每次要加入一个元素,先判断是否已经存在与堆中,若存在,那么value + 1返回,若不存在就加入堆中,然后判断堆中的个数是否已经大于size规定个数,若大于则进行弹出,因为是小顶堆,弹出的一定是最近使用次数最少的。