python實現LRU緩存淘汰

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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章