Redis缓存删除略和内存淘汰策略及LRU

1、Redis内存若在配置文件中未设置,内存会无限制增长,直到超出物理内存,抛出out of memory内存耗尽异常

        解决方法,调整maxmemory参数,一般设置为物理内存的3/4,并且添加缓存删除策略

2、Redis对于设置了过期时间的的键并不是过期立马删除,有三种缓存删除方案

        1、定时删除,定时任务去遍历所有过期键值,会占用cpu和影响性能

        2、惰性删除,过期了并不删,下次用到再删,会占用memory和内存泄漏

        3、定期删除,每过一段时间抽取一部分过期了的键删除,这种需要考虑具体的内存使用情况,配置好合理的定期时间。但依然会内存泄漏,需要兜底方案也就是内存淘汰策略。

3、Redis内存淘汰策略,可使用config set xxx命令或者修改配置文件种memory-policy

           分为两类,每类四种

所有key
allkeys-lru 对所有key使用lru算法
allkeys-lfu 对所有key使用lfu算法
allkeys-random 对所有key使用随机删除算法
noviction 不删除任何key(默认)
设置了过期时间的key
volatite-lru 对设置了过期时间的key使用lru算法
volatite-lfu 对设置了过期时间的key使用lfu算法
volatite-random 对设置了过期时间的key使用随机删除
volatite-ttl 删除过期的key

 4、lru算法-淘汰不经常使用的key,思路每次get或者put时,将数据重新插入,超过内存限制则删除最前面的数据。

public class LRUCache {

    private final Map map = new LinkedHashMap();

    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底层实现

你可能感兴趣的:(缓存,redis,数据库)