FIFO LRU LFU三種快取演算法

2021-10-03 10:01:38 字數 3533 閱讀 1465

先進先出,如果快取容量滿,則優先移出最早加入快取的資料;其內部可以使用佇列實現。

1)object get(key):獲取儲存的資料,如果資料不存在或者已經過期,則返回null。

2)void put(key,value,expiretime):加入快取,無論此key是否已存在,均作為新key處理(移除舊key);如果空間不足,則移除已過期的key,如果沒有,則移除最早加入快取的key。過期時間未指定,則表示永不自動過期。

3)此題需要注意,我們允許key是有過期時間的,這一點與普通的fifo有所區別,所以在設計此題時需要注意。(也是面試考察點,此題偏設計而非演算法)

普通的fifo或許大家都能很簡單的寫出,此處增加了過期時間的特性,所以在設計時需要多考慮。如下示例,為fifo的簡易設計,尚未考慮併發環境場景。

1)用普通的hashmap儲存快取資料。

2)我們需要額外的map用來儲存key的過期特性,例子中使用了treemap,將「剩餘存活時間」作為key,利用treemap的排序特性。

public class fifocache   

public object get(string key)

//如果不包含過期時間

long expired = value.expired;

long now = system.nanotime();

//已過期

if (expired > 0 && expired <= now)

return value.value;

} public void put(string key,object value)

public void put(string key,object value,int seconds)

//一次移除所有過期key

string _value = expired.get(_key);

cache.remove(_value);

iterator.remove();

} }

//如果仍然容量不足,則移除最早訪問的資料

if (capacity < cache.size())

iterator.remove();

} }

//如果此key已存在,移除舊資料

value current = cache.remove(key);

if (current != null && current.expired > 0)

//如果指定了過期時間

if(seconds > 0) else

} private long expiredtime(int expired)

public void remove(string key)

long expired = value.expired;

if (expired > 0)

} class value

} }

least recently used,最近最少使用,是目前最常用的快取演算法和設計方案之一,其移除策略為「當快取(頁)滿時,優先移除最近最久未使用的資料」,優點是易於設計和使用,適用場景廣泛。演算法可以參考leetcode 146 (lru cache)。

1)object get(key):從canche中獲取key對應的資料,如果此key已過期,移除此key,並則返回null。

2)void put(key,value,expired):設定k-v,如果容量不足,則根據lru置換演算法移除「最久未被使用的key」,需要注意,根據lru優先移除已過期的keys,如果沒有,則根據lru移除未過期的key。如果未設定過期時間,則認為永不自動過期。

3)此題,設計關鍵是過期時間特性,這與常規的lru有所不同。畢竟「過期時間」特性在cache設計中是必要的。

1)lru的基礎演算法,需要了解;每次put、get時需要更新key對應的訪問時間,我們需要乙個資料結構能夠儲存key最近的訪問時間且能夠排序。

2)既然包含過期時間特性,那麼帶有過期時間的key需要額外的資料結構儲存。

3)暫時不考慮併發操作;盡量兼顧空間複雜度和時間複雜度。

4)此題仍然偏向於設計題,而非純粹的演算法題。

此題**與fifo基本相同,唯一不同點為get()方法,對於lru而言,get方法需要重設訪問時間(即調整所在cache中順序)

public object get(string key)   

//如果不包含過期時間

long expired = value.expired;

long now = system.nanotime();

//已過期

if (expired > 0 && expired <= now)

//相對於fifo,增加順序重置

cache.remove(key);

cache.put(key,value);

return value.value;

} 複製**lfu

最近最不常用,當快取容量滿時,移除訪問次數最少的元素,如果訪問次數相同的元素有多個,則移除最久訪問的那個。設計要求參見leetcode 460( lfu cache)

public class lfucache

public object get(string key)

touch(key);

return keytovalue.get(key);

} /**

* 如果乙個key被訪問,應該將其訪問次數調整。

* @param key

*/

private void touch(string key)

//然後將此key的統計資訊加入到管理列表中

linkedhashsetcountkeys = counttolrukeys.get(count + 1);

if (countkeys == null)

countkeys.add(key);

} public void put(string key, object value)

if (keytovalue.containskey(key))

//容量超額之後,移除訪問次數最少的元素

if (keytovalue.size() >= capacity)

keytocount.remove(evictkey);

keytovalue.remove(evictkey);

} keytovalue.put(key, value);

keytocount.put(key, 1);

linkedhashsetkeys = counttolrukeys.get(1);

if (keys == null)

keys.add(key);

} }

FIFO LRU LFU三種快取演算法

先進先出,如果快取容量滿,則優先移出最早加入快取的資料 其內部可以使用佇列實現。1 object get key 獲取儲存的資料,如果資料不存在或者已經過期,則返回null。2 void put key,value,expiretime 加入快取,無論此key是否已存在,均作為新key處理 移除舊k...

FIFO LRU LFU三種演算法

提到快取,有兩點是必須要考慮的 1 快取資料和目標資料的一致性問題。2 快取的過期策略 機制 其中,快取的過期策略涉及淘汰演算法。常用的淘汰演算法有下面幾種 1 fifo firstin first out 先進先出 2 lru leastrecently used 最近最少使用 3 lfu lea...

三種快取模式(Cache Pattern)

cup和記憶體資料交換的效率不高,這是指令流水線式處理器的瓶頸之一。我們可以通過儲存層次 memory hierarchy 的方式來解決這個問題。這個儲存層次內有 1 容量小的 高速的快取 2 容量較大的 慢一點記憶體 3 容量很大的 但很慢的硬碟 2 檢查記憶體 main memory 如果a在主...