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;}@Overrideprotected 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底层实现