过期策略

定时删除

Redis 默认是每隔 100ms 就随机抽取一些设置了过期时间的 key,检查其是否过期,如果过期就删除。

惰性删除

并非是 key 到期了就会被自动删除,而是每次获取 key 时,才检査 key 是否过期,如果过期就删除。

内存淘汰策略

当 Redis 的内存空间(maxmemory 参数配置)已经用满时,Redis 将根据配置的淘汰策略(maxmemory-policy 参数配置),进行相应的动作。

  • noeviction默认策略,不淘汰任何 key,直接返回错误
  • allkeys-lru:在所有的 key 中,使用 LRU 算法淘汰部分 key
  • allkeys-lfu:在所有的 key 中,使用 LFU 算法淘汰部分 key(Redis 4.0 新增)
  • allkeys-random:在所有的 key 中,随机淘汰部分 key
  • volatile-lru:在设置了过期时间的 key 中,使用 LRU 算法淘汰部分 key
  • volatile-lfu:在设置了过期时间的 key 中,使用 LFU 算法淘汰部分 key(Redis 4.0 新增)
  • volatile-random:在设置了过期时间的 key 中,随机淘汰部分 key
  • volatile-ttl:在设置了过期时间的 key 中,挑选 TTL(time to live,剩余时间)短的 key 淘汰

LRU:淘汰最长时间没有被使用的 LFU:淘汰一段时间内,使用次数最少的

手动实现一个 LRU 算法

原理

将原先的 key-val 再次封装成一个 node。让整体形成一个双链表。然后维护头结点和尾节点,以及一个阈值。 当一个 key 被查询的时候,就将这个 key 从原来的地方删除,然后再次插入到尾节点处。 如果在添加 key 的时候,发现内存达到了阈值,那么就删除头结点的 key。(因为最近调用的节点都重新插入链尾了,在链头结点的就是最近最少使用的 key) 这样就保证了每次淘汰都是最旧的数据。而热点数据可以长时间存在。

public class LRUCache<K, V> extends LinkedHashMap<K, V> {
    private final int CACHE_SIZE;
    //这里就是传递进来最多能缓存多少数据
    public LRUCache(int cacheSize) {
        //设置一个hashmap 的初始大小,最后一个true指的是让linkedhashmap
        //按照访问顺序来进行排序,最近访问的放在头,最老访问的就在尾
        super((int) Math.ceil(cacheSize / 0.75) + 1, 0.75f, true); 
        CACHE_SIZE = cacheSize;
    }
    
    @Override
    protected boolean removeEldestEntry(Map.Entry eldest) {
        //当map中的数据量大于指定的缓存个数的时,自动删除最老的数据
        return size() > CACHE_SIZE; 
    }
}   

参考链接

Info