大家好,我系渣渣骥,今天跟大家分享的主题是: Redis有哪些内存回收策略,手写代码实现一个LRU缓存?
Redis支持的内存回收策略如下:
1.volatile-lru:从已设置过期的数据集中挑选最近最少使用的淘汰
2.volatile-ttl:从已设置过期的数据集中挑选将要过期的数据淘汰
3.volatile-random:从已设置过期的数据集中任意挑选数据淘汰
4.allkeys-lru:从所有数据集中挑选最近最少使用的数据淘汰
5.allkeys-random:从所有数据集中任意挑选数据淘汰
6.noenviction:禁止淘汰数据
在Redis的配置文件(redis.conf)中有一个maxmemory-policy专门用于配置内存回收策略。默认是noenviction,但是生产环境不建议使用,建议根据业务特点选择使用allkeys-lru、volatile-lru或者volatile-ttl.
需要注意的是,为了保证高性能,在LRU和TTL算法中,Redis不会对全部的键值进行比较,而是采用了近似的算法。例如,使用maxmemory-policy=volatile-ttl策略,另一个参数maxmemory-samples为3,按照探测顺序,有A,B,C,D,E五个KEY即将过期,即将过期时间分别为6s, 3s,2s,1s,9s. 由于maxmemory-samples为3, Redis不会将A、B、C、D、E都进行比较,而是将前3个A、B、C进行比较,发现C只有2s就要过期为最小,于是淘汰了C。可见,maxmemory-samples越大,淘汰越准确,但是效率也就越低。
那么如何实现一个LRU缓存呢?可以参考leetcode 146题:实现一个LRU缓存。这里提供一种思路:直接利用LinkedHashMap, 覆写其removeEldestEntry(Map.Entry eldest) 方法,在超过总长度时删除最不常用的一个元素。参考代码如下:
importjava.util.*;
classLRUCache extends LinkedHashMap<Integer,Integer>{
private int maxNum;
public LRUCache(int capacity) {
super(capacity, 0.75f, true);
this.maxNum = capacity;
}
public int get(int key) {
return super.getOrDefault(key, -1);
}
public void put(int key, int value) {
super.put(key, value);
}
protected boolean removeEldestEntry(Map.Entryeldest) {
return size() > maxNum;
}
}
如果不用LinkedHashMap,只需要记录元素的使用次数。每次加入时移除最少使用的那个元素即可。
用户评论