圖解緩存淘汰算法一之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類
相關文章
相關標籤/搜索