LRU cache原理及go實現

2021-09-11 12:54:31 字數 1515 閱讀 6042

1.1 概述

快取資源通常比較昂貴,通常資料量較大時,會竟可能從較少的快取滿足盡可能多訪問,這裡有一種假設,通常最近被訪問的資料,那麼它就有可能會被後續繼續訪問,基於這種假設,將所有的資料按訪問時間進行排序,並按驅逐出舊資料,那麼存在快取的資料就為熱點資料,這樣既節省了記憶體資源,又極大的滿足了訪問.lru(least recently used)演算法就是基於這種假設的一直快取置換演算法.

1.2 演算法流程

假設快取大小為4,而寫入順序為a b c d e d f.訪問順序分為寫入以及讀取兩種操作,寫入需要更新訪問時間,並且當資料到達最大快取時需要逐出資料,而讀取只會更新訪問時間,寫入置換演算法流程如上圖所示.

當未到達快取大小時,所有資料按寫入儲存,並記錄寫入次序.

寫入e時快取已經滿,且e的值不存在,需要逐出最久未訪問的資料a,此時快取內容為e d c b.

下乙個寫入d, d在快取中,直接更新d的訪問次序,此時快取內容為 d e c b

下乙個寫入f, f不在快取中,逐出快取中的末尾c,此時快取內容為 f d e c

2.1思路

採用go,可以使用list加map實現lru cache,具體思路為:

寫入時,先從map中查詢,如果能查詢,如果能查詢到值,則將該值的在list中移動到最前面.如果查詢不到值,則判斷當前map是否到達最大值,如果到達最大值則移除list最後面的值,同時刪除map中的值,如果map容量未達最大值,則寫入map,同時將值放在list最前面.

讀取時,從map中查詢,如果能查詢到值,則直接將list中該值移動到最前面,返回查詢結果.

為保證併發安全,需要引入讀寫鎖.

另外,存在讀取list中內容反差map的情況,因為宣告乙個容器物件同時儲存key以及value, list中以及map中儲存的都是容器物件的引用.

引入原子物件對命中數以及未命中數等指標進行統計

2.2 關鍵**

完整**見:cache

func (c *memcache) set(key string, value inte***ce{}) ]*list.element)

c.cachelist = list.new()

} //判斷是否在map中,如果在map中,則將value從list中移動到前面.

if ele, ok := c.cache[key]; ok

//如果不再map中,將值存到list最前面

ele := c.cachelist.pushfront(&entry)

c.cache[key] = ele

//判斷是否到達容量限制,到達容量限制時刪除list中最後面的值.

if c.maxitemsize != 0 && c.cachelist.len() > c.maxitemsize

}複製**

func (c *memcache) get(key string) (inte***ce{}, bool) 

return nil, false

}複製**

wiki_lru

LruCache實現原理

lrucache 什麼是lrucache?lrucache實現原理是什麼?這兩個問題其實可以作為乙個問題來回答,知道了什麼是 lrucache,就只然而然的知道 lrucache 的實現原理 lru的全稱是least recently used 近期最少使用的!所以我們可以推斷出 lrucache ...

談談LruCache演算法的底層實現原理及其內部原始碼

我們在對資料進行操作的時候,為了避免流量或者效能的消耗,我們對於一些資料都會進行快取處理,而對資料的快取的要點不僅僅只有我們所熟悉的儲存快取和使用快取,還有刪除快取。對於新增和獲取快取很好理解,那麼為什麼還要對快取進行刪除吶?原因很簡單,因為我們的手機容量是有限的,如果我們拼命的寫入快取,那麼終有一...

談談LruCache演算法的底層實現原理及其內部原始碼

我們在對資料進行操作的時候,為了避免流量或者效能的消耗,我們對於一些資料都會進行快取處理,而對資料的快取的要點不僅僅只有我們所熟悉的儲存快取和使用快取,還有刪除快取。對於新增和獲取快取很好理解,那麼為什麼還要對快取進行刪除吶?原因很簡單,因為我們的手機容量是有限的,如果我們拼命的寫入快取,那麼終有一...