本地缓存设计之FIFO,LRU淘汰策略实现

缓存的含义

缓存就是内存中的一个对象,可以基于此对象存储其它对象

缓存的作用

降低数据库的访问压力,提高数据的查询效率,改善用户体验

缓存的分类

  • 数据库内置的缓存?(例如 mysql 的查询缓存)
  • 数据层缓存(一般由持久层框架提供,例如 MyBatis)
  • 业务层缓存(基于 map 等实现的本缓存,分布式缓存-例如 redis)
  • 浏览器内置缓存?
  • CPU 缓存(高速缓冲区)

缓存设计要考虑哪些问题?

  • 存储结构(使用什么结构存储数据效率会更高?-散列表)
  • 淘汰策略(缓存容量有限-LRU/FIFO/LFU,软应用、弱引用)
  • 任务调度(定期刷新缓存,缓存失效时间)
  • 并发安全(缓存并发访问时的线程安全)
  • 日志记录(缓存是否命中,命中率是多少)
  • 序列化(存对象时序列化、取对象时反序列化

缓存接口设计

public interface Cache {
    void putObject(Object key,Object value);
    Object getObject(Object key);
    Object removeObject(Object key);
    void clear();
    int size();
}

1.基于HashMap实现简易缓存

public class PerpetualCache implements Cache{

    private HashMap<Object,Object> 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);
    }
    ...
}

2.基于Deque实现Fifo淘汰算法的缓存

public class FifoCache implements Cache{
    /**关联Cache对象-找到可以存储数据的基层对象*/
    private Cache cache;
    /**定义Cache的最大容量*/
    private int maxCap;
    /**通过队列记录key的添加顺序,Deque是JAVA中的双端队列,用于存储对应的key*/
    private Deque<Object> keyOrders;

    public FifoCache(Cache cache, int maxCap) {
        this.cache = cache;
        this.maxCap = maxCap;
        this.keyOrders=new LinkedList<>();
    }

    @Override
    public void putObject(Object key, Object value) {
        //1.记录key的顺序(通过添加在队列的尾部实现)
        keyOrders.addLast(key);
        //2.判断容器是否已满,满了则移除
        if (keyOrders.size()>maxCap){
            Object firstKey = keyOrders.removeFirst();
            //从cache中清除指定key对应的对象
            cache.removeObject(firstKey);
        }
        //3.向cache添加数据
        cache.putObject(key,value);
    }

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

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

3.基于LinkedHashMap实现LRU淘汰算法的缓存

/**关联Cache对象-找到可以存储数据的基层对象*/
    private Cache cache;
    /**定义Cache的最大容量*/
    private int maxCap;
    /**通过LinkedHashMap记录key的访问顺序*/
    private LinkedHashMap<Object,Object> keyAccessOrders;
    /**记录最近访问次数最少的key*/
    private Object eldEstKey;

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

    @Override
    public void putObject(Object key, Object value) {
        cache.putObject(key,value);
        keyAccessOrders.put(key,key);//2.记录key的访问顺序
        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;
    }
    ...
}

FAQ:

1.Fifo和LRU算法淘汰策略的区别?

First in First out 先进先出,   判断被存储的时间,离目前最远的数据优先被淘汰,   针对于内存中访问频率比较高,但是放入的时间又比较早的对象而言,命中率会比较低

Least Recently Used,最近最少使用。判断最近被使用的时间,目前最远的数据优先被淘汰.  LRU算法存在着“缓存污染”的情况需要避免,当突然有一批非热点元素查询打入,大量的非热点数据就会被加载到缓存队列中,从而把真正的热点元素给“挤出去”

2.LFU算法拓展

Least Frequently Used,最不经常使用。在一段时间内,数据被使用次数最少的,优先被淘汰 .需要耗费额外的空间来存储每个元素的访问频率,因此随着缓存元素的数目不断增大,计数器的个数也在不断地增大

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值