1、Redis内存若在配置文件中未设置,内存会无限制增长,直到超出物理内存,抛出out of memory内存耗尽异常
解决方法,调整maxmemory参数,一般设置为物理内存的3/4,并且添加缓存删除策略
2、Redis对于设置了过期时间的的键并不是过期立马删除,有三种缓存删除方案
1、定时删除,定时任务去遍历所有过期键值,会占用cpu和影响性能
2、惰性删除,过期了并不删,下次用到再删,会占用memory和内存泄漏
3、定期删除,每过一段时间抽取一部分过期了的键删除,这种需要考虑具体的内存使用情况,配置好合理的定期时间。但依然会内存泄漏,需要兜底方案也就是内存淘汰策略。
3、Redis内存淘汰策略,可使用config set xxx命令或者修改配置文件种memory-policy
分为两类,每类四种
所有key |
| ||||||||
设置了过期时间的key |
|
4、lru算法-淘汰不经常使用的key,思路每次get或者put时,将数据重新插入,超过内存限制则删除最前面的数据。
public class LRUCache {
private final Map<Integer, Integer> map = new LinkedHashMap<Integer, Integer>();
private int capacity;
public LRUCache(int capacity) {
this.capacity = capacity;
}
public int get(int key) {
if(!map.containsKey(key)){
return -1;
}
int v = map.get(key);
map.remove(key);
map.put(key, v);
return v;
}
public void put(int key, int value) {
map.remove(key);
map.put(key, value);
if(map.size() > capacity) {
map.remove(map.entrySet().iterator().next().getKey());
}
System.out.println(map);
}
public static void main(String[] args) {
LRUCache l = new LRUCache(2);
l.put(2,1);
l.put(1,1);
l.put(2,3);
l.put(4,1);
l.get(1);
}
}
5、实际上LinkedHashMap已经帮我们实现了lru算法,可以继承LinkedHashMap,具体如下
public class LRUCache extends LinkedHashMap {
private int capacity;
public LRUCache(int capacity) {
super(capacity, 0.75f, true);
this.capacity = capacity;
}
@Override
protected boolean removeEldestEntry(Map.Entry eldest) {
return super.size() > capacity;
}
public static void main(String[] args) {
LRUCache l = new LRUCache(2);
l.put(2,1);
l.put(1,1);
l.put(2,3);
l.put(4,1);
l.get(1);
l.get(2);
System.out.println(l);
}
}
6、如果不基于LinkedHashMap我们需要自己实现存储+顺序结构,可使用哈希+双向链表实现。可以参考HashMap与AQS底层实现