面試不再怕,程序員大佬教你20行Python代碼,搞懂LRU算法

LRU算法在后端工程師面試中,是一個比較常出現的題目,這篇文章帶大家一起,理解LRU算法,并最終用Python輕松實現一個基于LRU算法的緩存。

緩存是什么

先看一張圖,當我們訪問網頁,瀏覽器會給服務器發請求,服務器會經過一系列的運算,把頁面返回給瀏覽器。

當有多個瀏覽器同時訪問的時候,就會在短時間內發起多個請求,而服務器對每一個請求都要進行一系列相同的操作。重復工作不僅浪費資源,還可能導致響應速度變慢。

而緩存則可以把服務器返回的頁面保存下來,當有其他的瀏覽器再訪問時候,就不必勞服務器大駕,直接由緩存返回頁面。為了保證響應速度,緩存通常是基于比較昂貴的硬件,比如RAM,這就決定了我們很難用大量的緩存把所有的頁面都存下來,當恰好沒有緩存瀏覽器請求的頁面時,依然需要請求服務器。由于緩存容量有限,而數據量無限(互聯網每天新產生的頁面數無法估計),就需要把好剛用在刀刃上,緩存那些最有用的信息。

LRU是什么

LRU是一種緩存淘汰算法(在OS中也叫內存換頁算法),由于緩存空間是有限的,所以要淘汰緩存中不常用的數據,留下常用的數據,達到緩存效率的最大化。LRU就是這樣一種決定“淘汰誰留下誰”的算法,LRU是Least recently used的縮寫,從字面意思“最近最少使用”,我們就可以理解LRU的淘汰規則。

LRU的淘汰邏輯

我們用一張圖來描述LRU的淘汰邏輯,圖中的緩存是一個列表結構,上面是頭結點下面是尾節點,緩存容量為8(8個小格子):

有新數據(意味著數據之前沒有被緩存過)時,加入到列表頭

緩存到達最大容量時,需要淘汰數據多出來的數據,此時淘汰列表尾部的數據

當緩存中有數據被命中,則將數據移動到列表頭部(相當于新加入緩存)

按上面的邏輯我們可以看到,一個數據如果經常被訪問就會不斷地被移動到列表頭部,不會被淘汰出緩存,而越不經常訪問的數據,越容易被擠出緩存。

【【python學習交流裙,181670897.進裙邀請碼(編號):寂靜 。裙內不定時分享干貨,包括2018最新的企業案例學習資料和零基礎入門教程,歡迎自學的小白和大神】

20行Python代碼實踐LRU

接下來我們用Python來實現一個采用LRU算法的緩存。

從前面的文章中我們可以知道,緩存簡化下來就兩個功能,一個是往里裝數據(緩存數據),一個是往外吐數據(命中緩存),所以我們的緩存對外只需要put和get兩個接口就可以了。

按照前面的示意圖,緩存內部我們只需要有一個列表(list)就可以實現LRU邏輯,不過用列表雖然能實現邏輯,但是在判斷是否命中緩存時,速度可能非常慢(列表需要遍歷才能知道數據有沒有在里面)。在Python中,我們可以用基于hash的結構,比如字典(dict)或集合(set),來快速判斷數據是否存在,解決列表實現的性能問題。但是字典和集合又是沒有順序的,如果能有一種既能排序,又是基于hash存儲的數據結構,就好了。

在Python的collections包中,已經內置了這種實用的結構OrderedDict,OrderedDict是dict的子類,但是存儲在內部的元素是有序的(列表的特點)。

解決了數據結構的問題,我們可以直接上手寫邏輯了,代碼如下:

class LRUCache:

? ? def __init__(self, capacity):

? ? ? ? self.capacity = capacity

? ? ? ? self.queue = collections.OrderedDict()

? ? def get(self, key):

? ? ? ? if key not in self.queue:

? ? ? ? ? ? return -1 // 要找的數據不在緩存中返回-1

? ? ? ? value = self.queue.pop(key) // 將命中緩存的數據移除

? ? ? ? self.queue[key] = value // 將命中緩存的數據重新添加到頭部

? ? ? ? return self.queue[key]

? ? def put(self, key, value):

? ? ? ? if key in self.queue: // 如果已經在緩存中,則先移除老的數據

? ? ? ? ? ? self.queue.pop(key)

? ? ? ? elif len(self.queue.items()) == self.capacity:

? ? ? ? ? ? self.queue.popitem(last=False) // 如果不在緩存中并且到達最大容量,則把最后的數據淘汰

? ? ? ? self.queue[key] = value // 將新數據添加到頭部

下次面試在遇到LRU的題目,是不是就胸有成竹了?

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 今天開始分析YYCache 包含的文件類 YYCache YYMemoryCache YYDiskCache YY...
    充滿活力的早晨閱讀 814評論 4 1
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,869評論 18 139
  • Python 面向對象Python從設計之初就已經是一門面向對象的語言,正因為如此,在Python中創建一個類和對...
    順毛閱讀 4,236評論 4 16
  • 朋友們大家好! 早上起來才看見我們這里下雪了,空氣清新感覺心情舒暢了許多。 最近參加孵化營很緊張,雖然學到了很多東...
    笑看風云_9628閱讀 193評論 0 5
  • 現代社會其實是一個灑雞湯的社會,每個人都在灑雞湯,看誰灑的好,灑的多,灑的漂亮、如果你就一件事詢問別人的意見,你會...
    科恩先生閱讀 345評論 0 0