手写缓存之Lru缓存淘汰算法

文章目录

  • 前言
  • 一、Lru缓存淘汰算法是什么
  • 二、实现步骤
    • 1.接口
    • 2.接口实现类
    • 3.Lru淘汰算法实现
    • 4.运行结果演示
  • 总结


前言

随着近些年大型电商应用(例如京东、阿里巴巴等)的迅速发展,本地缓存和分布式缓存相关技术被大量的应用。那么这些缓存的核心算法都有哪些呢,上次给大家手写了FIFO先进先出算法的实现过程,感兴趣的可以通过手写缓存之FIFO先进先出算法来进行学习和回顾。那么今天给大家介绍的是Lru淘汰缓存算法。手写缓存之FIFO先进先出算法

一、Lru缓存淘汰算法是什么?

Lru算法是近些年来一些大型电商平台比较推荐的一种算法,其原理是在我们的缓存满了以后按照访问数量来进行淘汰,优先淘汰那些访问次数比较低的缓存数据,大家来看下面的示例图来加深理解。

手写缓存之Lru缓存淘汰算法_第1张图片

 大家可以从图中看出随着新数据的放入,没有被访问的数据或者访问次数较少的优先被淘汰掉。我们联想一下,当几个商品的数据被频繁访问,那么这些商品的数据就应该被一直保留在缓存中,当缓存满了要放入新的数据的时候,那么就会优先淘汰掉那些访问比较少的数据,来确保我们的缓存里面可以实现比较好的效果,最大程度的缓解数据库的压力。

二、实现步骤

这里和FIFO算法案例一样,先来写一个接口类,并做出实现此接口的实现类,在此基础上我们再去实现Lru算法。

1. 接口

代码如下(示例):

/**
 * Cache规范定义
 */
public interface Cache {
    void putObject(Object key,Object value);
    Object getObject(Object key);
    Object removeObject(Object key);
    void clear();
    int size();
}

2. 接口实现类

代码如下(示例):

/**
 * 简易Cache实现
 * 1)存储结构:散列表(基于JAVA中的hashmap存储)
 * 2)淘汰算法:没有(直到到内存溢出)
 * 3)线程安全:否
 * 4)缓存对对象的引用?强引用
 * 5)对象获取:浅拷贝(获取对象地址)
 */
public class PerpetualCache implements Cache{

    private HashMap cache=new HashMap<>();
    @Override
    public void putObject(Object key, Object value) {
        cache.put(key, value);
    }

    @Override
    public Object getObject(Object key) {
        return cache.get(key);
    }

    @Override
    public Object removeObject(Object key) {
        return cache.remove(key);
    }

    @Override
    public void clear() {
        cache.clear();
    }

    @Override
    public int size() {
        return cache.size();
    }

    @Override
    public String toString() {
        return "PerpetualCache{" +
                "cache=" + cache.toString() +
                '}';
    }
}

3. Lru淘汰算法实现

代码如下(示例):


/**
 * 基于LRU算法为缓存添加数据淘汰策略。
 */
public class LruCache implements Cache{
    /**关联Cache对象-找到可以存储数据的基层对象*/
    private Cache cache;
    /**定义Cache的最大容量*/
    private int maxCap;
    /**通过LinkedHashMap记录key的访问顺序*/
    private LinkedHashMap keyAccessOrders;
    /**记录最近访问次数最少的key*/
    private Object eldEstKey;

    public LruCache(Cache cache, int maxCap) {
        this.cache = cache;
        this.maxCap = maxCap;
        keyAccessOrders=new LinkedHashMap(maxCap,0.75f,true){
            @Override
            protected boolean removeEldestEntry(Map.Entry eldest) {
                boolean isFull= size()>maxCap;
                if(isFull)eldEstKey=eldest.getKey();//获取最近访问次数最少的key
                return isFull;
            }
        };
    }

    @Override
    public void putObject(Object key, Object value) {
        //1.向Cache中添加新的元素
        cache.putObject(key, value);
        //2.记录key的访问顺序
        keyAccessOrders.put(key, key);
        //3.Cache满了则移除最近访问次数最少的key/value
        if(eldEstKey!=null){
            cache.removeObject(eldEstKey);
            eldEstKey=null;
        }
    }

    @Override
    public Object getObject(Object key) {
        //1.记录key的访问顺序
        keyAccessOrders.get(key);
        //2.返回cache中的指定key对应的value
        return cache.getObject(key);
    }

    @Override
    public Object removeObject(Object key) {
        Object object = cache.removeObject(key);
        keyAccessOrders.remove(key);
        return object;
    }

    @Override
    public void clear() {
           cache.clear();
           keyAccessOrders.clear();
    }

    @Override
    public int size() {
        return cache.size();
    }

    @Override
    public String toString() {
        return "LruCache{" +
                "cache=" + cache.toString() +
                '}';
    }

    public static void main(String[] args) {
        Cache cache=new LruCache(//负责添加算法
                new PerpetualCache(),//负责存数据
                3);
        cache.putObject("A", 100);
        cache.putObject("B", 200);
        cache.putObject("C", 300);
        cache.getObject("A");
        cache.putObject("D", 400);
        cache.putObject("E", 500);
        System.out.println(cache);
    }

}

4. 运行结果演示

手写缓存之Lru缓存淘汰算法_第2张图片

期间我们访问了一次A数据 ,当放入D和E之后,没有被访问的B和C被淘汰了,A数据保存了下来并处于头的位置。


总结

通过以上的实现小案例,我们已经初步理解并实现了Lru淘汰算法。相对与FIFO先进先出算法更加智能化,所以被京东这些大型电商平台广泛应用,小伙伴们学会了吗?

你可能感兴趣的:(算法,开发语言,缓存,分布式,java)