Redis(七):Redis数据淘汰策略

1、Redis数据淘汰

Redis内存淘汰指的是用户存储的一些键被可以被Redis主动地从实例中删除,从而产生读miss的情况,内存的淘汰机制的初衷是为了更好地使用内存,用一定的缓存miss来换取内存的使用效率。

2、开启方式:

redis.conf中的maxmemory这个值来开启内存淘汰功能。 maxmemory为0的时候表示我们对Redis的内存使用没有限制。

maxmemory 

当Redis内存使用达到maxmemory阀值时,Redis就会根据用户配置的淘汰策略主动删除无用的key,以保证新数据的正常存入。 

3、数据淘汰策略

  • noeviction(默认的策略):当内存使用达到阈值的时候,所有引起申请内存的命令会报错。
  • allkeys-lru:在主键空间中,优先移除最近未使用的key。
  • volatile-lru:在设置了过期时间的键空间中,优先移除最近未使用的key。
  • allkeys-random:在主键空间中,随机移除某个key。
  • volatile-random:在设置了过期时间的键空间中,随机移除某个key。
  • volatile-ttl:在设置了过期时间的键空间中,具有更早过期时间的key优先移除。

介绍一种 LRU 算法。Redis 的 LRU 算法不是一个精确的实现,Redis 没有使用真实的 LRU 实现的原因,是因为这会消耗更多的内存。然而,近似值对使用 Redis 的应用来说基本上也是等价的。为 Redis 使用的 LRU 近似值和真实 LRU 之间的比较。

4、LRU

LRU(Least Recently Used)是一种常见的页面置换算法

核心思想是当缓存满时,会优先淘汰那些近期最少使用的缓存对象,有效的避免了OOM的出现。可以用栈的思想实现。把访问过的元素放置到栈顶(若栈中存在,则更新至栈顶;若栈中不存在则直接入栈),然后如果栈中元素数量超过限定值,则删除栈底元素(即最近最少使用的元素)。

基于数组和链表、栈、队列都可以实现LRU算法。需要自己写逻辑。java提供的LinkedHashMap已经实现了顺序的维护。

LinkedHashMap它使用了一个双向链表来存储Map中的Entry顺序关系,这种顺序有两种,一种是LRU顺序,一种是插入顺序,这可以由其构造函数public LinkedHashMap(int initialCapacity,float loadFactor, boolean accessOrder)的accessOrder来指定。所以,对于get、put、remove等操作,LinkedHashMap除了要做HashMap做的事情,还做些调整Entry顺序链表的工作。LruCache中将LinkedHashMap的顺序设置为LRU顺序来实现LRU缓存,每次调用get(也就是从内存缓存中取图片),则将该对象移到链表的尾端。调用put插入新的对象也是存储在链表尾端,这样当内存缓存达到设定的最大值时,将链表头部的对象(近期最少用到的)移除

public class LinkedMapLRU extends LinkedHashMap {

    //初始容量
    private int initialCapacity;

    private final ReentrantLock lock = new ReentrantLock();

    //加载因子
    static float loadFactor = 0.75f;

    //false基于插入顺序,true 基于访问顺序(get一个元素后,这个元素被加到最后,使用了LRU 最近最少被使用的调度算法)
    static boolean accessOrder = true;

    public LinkedMapLRU(int initialCapacity) {
        super(initialCapacity, loadFactor, accessOrder);
        this.initialCapacity = initialCapacity;
    }

    @Override
    public V put(K key, V value) {
        try {
            lock.lock();
            return super.put(key, value);
        } finally {
            lock.unlock();
        }
    }

    @Override
    public V get(Object key) {
        try {
            lock.lock();
            return super.get(key);
        } finally {
            lock.unlock();
        }
    }

    @Override
    public V remove(Object key) {
        try {
            lock.lock();
            return super.remove(key);
        } finally {
            lock.unlock();
        }
    }

    @Override
    public boolean removeEldestEntry(Map.Entry eldest) {
        if (size() > initialCapacity) {
            return true;
        }
        return false;
    }

    public void setMaxSize(int size) {
        this.initialCapacity = size;
    }

    public static void main(String[] args) {
        LinkedMapLRU lru = new LinkedMapLRU(3);
        lru.put(1, 1);
        lru.put(2, 2);
        lru.put(3, 3);
        lru.get(1);
        lru.put(4, 4);
        lru.put(5, 5);
        for (Integer key : lru.keySet()) {
            System.out.println("key:" + key );
        }
    }
}

 

你可能感兴趣的:(Redis)