图解缓存淘汰算法一之LRU

1.概念分析

       LRU(Least Recently Used),即最近最少使用.怎么理解这个概念呢?我一开始见到这个概念的时候,觉得"最近","最少"都是修饰使用的(从中文解释中能够看出),不过这种理解是错误的,最近是修饰最少的,故应该理解为"最近这段时间最少访问的,最少使用".java

      这样理解是否是更清晰一些呢?也就是说,LRU这种算法是会将近期最少使用的数据淘汰掉.这样说的话,LRU淘汰算法彷佛是将最近次数上使用最少的数据淘汰[1],其实否则,或者说理解的不确切,更准确地说,LRU算法是将近期最不会访问的数据淘汰掉[2](请注意[1]和[2]的不一样,[1]处注重了次数上的比较,[2]处却没有这层意义).它的核心思想是"若是数据最近被访问过,那么未来被访问的几率也很高".反过来讲,"若是数据最近这段时间一直都没有访问,那么未来被访问的几率也会很低".Well,我知道这两句都是伪命题,就好像说一我的最近一直倒霉,那么他一生都会倒霉.不过,LRU就是基于这种思想来的.若是一个指导思想自己就有不少问题,那么在指导现实行为时就更加荒唐了(彷佛有点形而上学的意味了...).算法

      所以,咱们在这里能够说,LRU是荒唐的,是简单粗暴的,是片面的.打住,彷佛变成了LRU的批斗会了.数组

      --那么LRU就一无可取了?缓存

      --不是的.LRU算法的优势在于简单,并且也能够解决一些实际问题.只不过没那么精确而已,不少时候LRU算法也会有很多冤假错案,原本不应剔除的数据就白白的牺牲掉了.可是咱们仍是要正式LRU的优势.spa

      下面就讲解LRU的算法实现..net

2.原理

我画了一个LRU淘汰算法的过程图:blog

 

 下面简单讲解一下(须要在这里说明一下,LRU通常采用链表方式实现,便于快速移动数据位置,虽然图中使用彷佛是数组方式):队列

  1. 一开始,缓存池是空的,缓存池中插入数据时不用担忧容量不足的事情.所以这个过程就是相似队列的FIFO(但不止这些);
  2. 在第5步将E插入到缓存池中后,缓存池已经满了(固然实际应用中不会让到达缓存池的尺寸,通常到70%左右就要考虑淘汰机制了);
  3. 当第6步将E插入缓存池的时候,发现缓存池已经满了,LRU会将最先加入到缓存池的数据淘汰掉(A,实在不要意思啊);
  4. 第7步,从缓存池中访问C,C被访问,从时间点上是最近最近访问的,将C移动到链表的头部(C侥幸暂时远离被淘汰的边缘);
  5. 第8步,将G插入缓存池中,G处于链表头部,B不幸被淘汰.

大体的过程就是这样,关于淘汰机制只是后面的三步中会用到,画出前面六步的过程只是说明,LRU插入元素的方式.在这个图中,我想你们应该能够明白为何使用链表,而不使用数组(链表的插入和删除的时间复杂度都是O(1)).get

3.优劣分析

 【命中率it

命中率较高,不过偶发性的状况对LRU的命中影响很大,同时也会引入不少数据污染(好比很长时间只访问一次的数据,在后期的文章中会涉及到这一话题,会有改进的方案).

 【复杂度

实现起来较为简单.

 【存储成本

几乎没有空间上浪费.

 【缺陷

仅仅从最近使用时间上考虑淘汰算法,没有考虑缓存单元的使用频率,可能会淘汰一些仍有价值的单元.

4.实现

暂时略,之后会采用伪代码和java语言的方式作简单的实现.

最后,若有哪里不正确的地方,请多多指教. 后续会将其余缓存淘汰算法一一介绍,敬请期待.

 

 相关文章:

  1. 缓存算法
  2. 缓存淘汰算法系列之1——LRU类
相关文章
相关标签/搜索