LRU
Least Recent used 最近最少使用算法,主要用於緩存淘汰.
主要目的就是把最近最少使用的數據移除內存,以加載其他數據
原理:
有新數據(意味着數據之前沒有被緩存過)時,加入到列表頭
緩存達到最大容量時, 需要淘汰數據多出來的數據,此時淘汰列表尾部的數據
當緩存中有數據被命中, 則將數據移動到列表頭部(相當於新加入緩存)
從前面的文章中我們可以知道,緩存簡化下來就兩個功能,一個是往裏裝數據(緩存數據),一個是往外吐數據(命中緩存),所以我們的緩存對外只需要put和get兩個接口就可以了。
緩存內部我們只需要有一個列表(list)就可以實現LRU邏輯,不過用列表雖然能實現邏輯,但是在判斷是否命中緩存時,速度可能非常慢(列表需要遍歷才能知道數據有沒有在裏面)。在Python中,我們可以用基於hash的結構,比如字典(dict)或集合(set),來快速判斷數據是否存在,解決列表實現的性能問題。但是字典(python3.6後有序)和集合又是沒有順序的,如果能有一種既能排序,又是基於hash存儲的數據結構,就好了。
在Python的collections包中,已經內置了這種實用的結構OrderedDict,OrderedDict是dict的子類,但是存儲在內部的元素是有序的(列表的特點)。
from collections import OrderedDict
class LRUCache:
def __init__(self, capacity):
self.capacity = capacity
self.queue = OrderedDict()
def get(self, key):
# 要找的數據不再緩存中返回-1
if key not in self.queue:
return -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