什么是緩存?
舉個例子,去圖書館查資料,一般情況下我們會集中把我們有可能查閱的幾本書從書架取下來,放在我們的桌面上,以便交叉查閱,從而避免頻繁的從座位上跑到書架旁去取書。在這個例子里,書桌所扮演的就是緩存的角色。
緩存有兩個特點:
- 能在某種程度上降低訪問數據的成本;
- 其容量遠小于外部存儲的容量,如本例子中,書桌上能容納的書本數就遠小于書架的。
什么是 LRU 緩存?
LRU(Least Recently Used) 緩存是一種以 LRU 策略為緩存策略的緩存。而所謂的緩存策略,就是當緩存滿了之后,又有新數據需要加入到緩存中時,我們怎么從緩存中刪除舊數據為新數據騰出空間的策略。
依舊以圖書館為例,假設我們的書桌上只能容納 3 本書,并且已經放了 3 本書在上面,此時我們需要查閱第 4 本書,那么我們就必須權衡將原先書桌上的 3 本書的中的哪一本放回書架去。這個權衡的過程就是所謂的緩存策略。
LRU,Least Recently Used 的簡寫,即近期最少使用算法。該算法依據于程序的局部性原理, 其淘汰舊數據的策略是,距離當前最久沒有被訪問過的數據應該被淘汰。
基于雙鏈表 的LRU實現:
傳統意義的LRU算法是為每一個Cache對象設置一個計數器,每次Cache命中則給計數器+1,而Cache用完,需要淘汰舊內容,放置新內容時,就查看所有的計數器,并將最少使用的內容替換掉。
它的弊端很明顯,如果Cache的數量少,問題不會很大, 但是如果Cache的空間過大,達到10W或者100W以上,一旦需要淘汰,則需要遍歷所有計算器,其性能與資源消耗是巨大的。效率也就非常的慢了。
它的原理: 將Cache的所有位置都用雙連表連接起來,當一個位置被命中之后,就將通過調整鏈表的指向,將該位置調整到鏈表頭的位置,新加入的Cache直接加到鏈表頭中。
這樣,在多次進行Cache操作后,最近被命中的,就會被向鏈表頭方向移動,而沒有命中的,而想鏈表后面移動,鏈表尾則表示最近最少使用的Cache。
當需要替換內容時候,鏈表的最后位置就是最少被命中的位置,我們只需要淘汰鏈表最后的部分即可。
上面說了這么多的理論, 下面用代碼來實現一個LRU策略的緩存。
我們用一個對象來表示Cache,并實現雙鏈表。
這個問題在面試被問了,然后說了一句:這個我不會,回來查閱一下,大致了解一下。