上篇介紹了多級快取,本章詳細介紹下記憶體快取該如何設計。
閱讀目錄:
分析設計
o(1)lru實現
過期刪除策略
總結假設有個專案有比較高的併發量,要用到多級快取,如下:
在實際設計乙個記憶體快取前,需要考慮的問題:
2:記憶體容量的限制,需要控制快取數量。
3:熱點資料更新不同,需要可配置單個key過期時間。
4:良好的快取過期刪除策略。
5:快取資料結構的複雜度盡可能的低。
關於置換及命中率:採用lru演算法,因為它實現簡單,快取key命中率也很好。
lru即是:把最近最少訪問的資料給淘汰掉,經常被訪問到即是熱點資料。
關於lru資料結構:因為key優先順序提公升和key淘汰,所以需
要順序結構,網上
大多實現都採用的這種鍊錶結構。
即新資料插入到鍊錶頭部、被命中時的資料移動到頭部,
新增複雜度
o(1),移動和獲取複雜度o(n)。
有沒複雜度更低的呢? 有dictionary,複雜度為o(1),效能最好。 那如何保證快取的優先順序提公升呢?
定義個lrucache類,構造引數maxkeysize 來控制快取最大數量。
使用concurrentdictionary來作為我們的快取容器,並能保證執行緒安全。
public上面定義了 agetodiscard、currentage 這2個自增值引數,作用是class lrucache: ienumerablestring, tvalue>>
}
標記快取列表中各個key的新舊程度。
實現步驟如下:
每次新增key時,currentage自增並將currentage值分配給這個快取值的age,currentage一直自增。
public在新增時,如超過最大數量,檢查字典裡是否有agetodiscard年齡的key,如沒有迴圈自增檢查,有則刪除、新增成功。void add(string
key, tvalue value)
public
class
trackvalue
}
其agetodiscard+maxsize=
currentage ,這樣設計就能在o(1)下保證可以淘汰舊資料,而不是使用鍊錶移動。
public獲取key的時候表示它又被人訪問,將最新的currentage賦值給它,增加它的年齡:void adjust(string
key)
}
public tvalue get(string大多數情況下,lru演算法對熱點資料命中率是很高的。 但如果突然大量偶發性的資料訪問,會讓記憶體中存放大量冷資料,也即是快取汙染。key)
return
value.value;
}
會引起lru無法命中熱點資料,導致快取系統命中率急劇下降,也可以使用lru-k、2q、mq等變種演算法來提高命中率。
通過設定最大過期時間來盡量避免冷資料常駐記憶體。
多數情況每個資料快取的時間要求不一致的,所以需要再增加單個key的過期時間字段。
private關於key過期刪除,最好的方式是使用定時刪除,這樣可以最快的釋放被占用的記憶體,但很明顯大量的定時器對cpu來說是非常不友好的。timespan maxtime;
public lrucache(int
maxkeysize,timespan maxexpiretime){}
//trackvalue增加建立時間和過期時間
public
readonly
datetime createtime;
public
readonly timespan expiretime;
所以需要採用惰性刪除、在獲取key的時檢查是否過期,過期直接刪除。
public tuplebool> checkexpire(string惰性刪除雖然效能最好,但對於冷資料來說還是沒解決快取汙染的問題,所以還需增加個定期清理和惰性刪除配合使用。key)
}return tuple.create(result, true
); }
比如單開個執行緒每5分鐘去遍歷檢查key是否過期,這個時間策略是可配置的,如果快取數量較多可分批遍歷檢查。
public惰性刪除配合定期刪除基本上能滿足絕大多數要求了。void
inspection()
}
如果繼續完善下去就是記憶體資料庫的雛形,類似redis,比如增加刪除key的通知**,支援更多的資料型別儲存。
系列目錄:
那些年我們一起追過的快取寫法(一)
那些年我們一起追過的快取寫法(二)
那些年我們一起追過的快取寫法(三)
那些年我們一起追過的快取寫法 一
本篇主要介紹下樓主平常專案中,快取使用經驗和遇到過的問題。基本寫法 快取雪崩 全域性鎖,例項鎖 字串鎖 快取穿透 再談快取雪崩 總結為了方便演示,這裡使用runtime.cache做快取容器,並定義個簡單操作類。如下 public class cachehelper public static vo...
那些年我們一起追過的Shell Script
原本這是自己在幾個月前為公司的乙個分享活動寫的乙個投影片,今天趁大腦負荷比較小,把這個話題拿到blog上面來分享一下。從知道shell算起至今也就幾個年頭而已,如今勉強算是入門了。對某乙個新事物的掌握總是乙個循序漸近的過程,只是根據不一樣事物的特點,其學習的曲線也不盡一致。shell script算...
那些年我們一起追過的流量
前一段的熱播電影 那些年我們一起追過的女孩 很多人討論問什麼最後男女主角沒有在一起,這個麼仁者見仁,智者見智。我借這個東風,聊一聊那些年我們追過的流量,分析一下問什麼客戶不願意和自己 在一起。這些都是筆者以前做過的和看到的例子。1.關於程式設計客棧問答平台 搜搜問問 天涯問答等 以dtaye知道為例...