缓存置换策略-LRU算法

LRU算法

LRU算法定义:  

  LRU算法是指最近最少使用算法,意思是LRU认为最近使用过的数据,将来被访问的概率会大,最近没有被访问的数据意味着以后刚问的概率小。

 

为何要用LRU算法:

  1、我们的存储空间是有限的,当存储空间满了之后,要删除哪些数据呢,才能会时缓存的命中率高一些呢

  2、LRU算法还是比较简单的。

 

算法:

  最常见的算法是使用一个链表来实现

    1)将新数据插入到表头

    2)每当缓存命中时,将数据移动到表头

    3)当l存储空间满了的时候将链表尾部的数据删除

  缺点:链表实现,需要遍历链表找到命中的数据

  java中最简单的LRU算法实现,就是利用jdk的LinkedHashMap。 LinkedHashMap底层就是用的HashMap加双链表实现的,而且本身已经实现了按照访问顺序的存储。此外,LinkedHashMap中本身就实现了一个方法removeEldestEntry用于判断是否需要移除最不常读取的数,方法默认是直接返回false,不会移除元素,所以需要重写该方法。即当缓存满后就移除最不常用的数。(通过覆盖这个方法,加入一定的条件,满足条件返回true。当put进新的值方法返回true时,便移除该map中最老的键和值。)

 

算法分析:

  偶发性的、周期性的批量操作(可能不是热点数据)会使临时数据涌入缓存,挤出热点数据,导致LRU热点命中率急剧下降,缓存污染情况比较严重。

  

public class LRU<K,V> {
 
  private static final float hashLoadFactory = 0.75f;
  private LinkedHashMap<K,V> map;
  private int cacheSize;
 
  public LRU(int cacheSize) {
    this.cacheSize = cacheSize;
    int capacity = (int)Math.ceil(cacheSize / hashLoadFactory) + 1;
    map = new LinkedHashMap<K,V>(capacity, hashLoadFactory, true){
      private static final long serialVersionUID = 1;
 
      @Override
      protected boolean removeEldestEntry(Map.Entry eldest) {
        return size() > LRU.this.cacheSize;
      }
    };
  }
 
  public synchronized V get(K key) {
    return map.get(key);
  }
 
  public synchronized void put(K key, V value) {
    map.put(key, value);
  }
 
  public synchronized void clear() {
    map.clear();
  }
 
  public synchronized int usedSize() {
    return map.size();
  }
 
  public void print() {
    for (Map.Entry<K, V> entry : map.entrySet()) {
      System.out.print(entry.getValue() + "--");
    }
    System.out.println();
  }
}

 

 LRU-K算法

  LRU-K算法定义:

    LRU-K中的K代表最近使用的次数,因此LRU可以认为是LRU-1。LRU-K的主要目的是为了解决LRU算法“缓存污染”的问题,其核心思想是将“最近使用过1次”的判断标准扩展为“最近使用过K次”。

  算法实现:

    相比LRU,LRU-K需要多维护一个队列,用于记录所有缓存数据被访问的历史。只有当数据的访问次数达到K次的时候,才将数据放入缓存。当需要淘汰数据时,LRU-K会淘汰第K次访问时间距当前时间最大的数据。详细实现如下:

  1. 数据第一次被访问,加入到访问历史列表;

  2. 如果数据在访问历史列表里后没有达到K次访问,则按照一定规则(FIFO,LRU)淘汰;

  3. 当访问历史队列中的数据访问次数达到K次后,将数据索引从历史队列删除,将数据移到缓存队列中,并缓存此数据,缓存队列重新按照时间排序;

  4. 缓存数据队列中被再次访问后,重新排序;

  5. 需要淘汰数据时,淘汰缓存队列中排在末尾的数据,即:淘汰“倒数第K次访问离现在最久”的数据。

 

 

posted @ 2020-02-16 20:08  以梦为码  阅读(944)  评论(0编辑  收藏  举报