摘要:在上圖中,一旦充滿所分配的內存塊,那么最新出現的將替代最低使用的,訪問順序為。滿額時,從鏈表尾部開始往前刪除指定數目的數據,即可解決。
LRU
Discards the least recently used items first. This algorithm requires keeping track of what was used when, which is expensive if one wants to make sure the algorithm always discards the least recently used item. General implementations of this technique require keeping "age bits" for cache-lines and track the "Least Recently Used" cache-line based on age-bits. In such an implementation, every time a cache-line is used, the age of all other cache-lines changes.
在上圖中,一旦 A B C D 充滿所分配的內存塊,那么最新出現的 E 將替代最低使用的 A(0),訪問順序為 A -> B -> C -> D -> E -> D -> F。
原理這里將會出現一個性能瓶頸,也就是在 Cache 滿時,淘汰那些不常用的數據,空出空間存儲新的數據。假設每一條數據都有一個最后訪問時間, 當滿額的時候,將要遍歷所有元素,才能刪除訪問時間最小的那個元素,時間復雜度為 $O(1)$,數據量越大,性能越低。
所以選擇使用 鏈表,每訪問一次數據,把最新的訪問數據放至頭部,那尾部的數據就是最舊未訪問的數據。 滿額時,從鏈表尾部開始往前刪除指定數目的數據,即可解決。
代碼實現class LruCache { constructor(maxsize) { this._cache = {}; // 緩存 this._queue = []; // 隊列 this._maxsize = maxsize; // 最大值 // 如果最大值輸入非法 默認無限大 if (!this._maxsize || !(typeof this._maxsize === "number") || this._maxsize <= 0) { this._maxsize = Infinity; } // 運行定時器,定時檢查過期值 setInterval(() => { this._queue.forEach((el, idx) => { const key = el; const insertTime = this._cache[key].insertTime; const expire = this._cache[key].expire; const curTime = +new Date(); // 如果存在過期時間且超期,移除數據 if (expire && curTime - insertTime > expire) { this._queue.splice(idx--, 1); delete this._cache[key]; } }); }, 1000); } // 生成唯一索引 _makeSymbol(key) { return Symbol.for(key); } // 更新隊列 _update(queue, key) { // 移除 queue.forEach((el, idx) => { if (el === key) { queue.splice(idx, 1); } }); // 前置 queue.unshift(key); return queue; } // 插入數據 set(key, value, expire) { key = this._makeSymbol(key); // 生成唯一索引 // 如果已經存在該值,則重新賦值 if (this._cache[key]) { this._cache[key] = { value, expire, insertTime: this._cache[key].insertTime } this._queue = this._update(this._queue, key); // 更新隊列 } else { // 如果不存在,則插入 this._cache[key] = { value, expire, insertTime: +new Date() } // 索引置前 this._queue.unshift(key); // 超出最大值,截斷 while (this._queue.length > this._maxsize) { const item = this._queue.pop(); // 尾截斷 delete this._cache[item]; // 刪除 } } } // 獲取數據 get(key) { key = this._makeSymbol(key); // 如果存在該值 if (this._cache[key]) { const insertTime = this._cache[key].insertTime; // 插入時間 const expire = this._cache[key].expire; // 過期時間 const curTime = +new Date(); // 當前時間 // 如果不存在過期時間 或 存在過期時間但尚未過期 if (!expire || (expire && curTime - insertTime < expire)) { // 更新隊列,前置索引 this._queue = this._update(this._queue, key); return this._cache[key].value; } else if (expire && curTime - insertTime > expire) { // 已經過期 this._queue.forEach((el, idx) => { if (el === key) { this._queue.slice(idx, 1); delete this._cache[key]; } }) return null } } else { return null; } } }
同步至我的個人博客:https://blog.trevor.top/item/34
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/94639.html
摘要:如果處理不得當,就會造成緩存污染問題。解決緩存污染的算法算法,英文名,字面意思就是最不經常使用的淘汰掉算法,是通過數據被訪問的頻率來判斷一個數據的熱點情況。分析降低了緩存污染帶來的問題,命中率比要高。 微信公眾號:IT一刻鐘大型現實非嚴肅主義現場一刻鐘與你分享優質技術架構與見聞,做一個有劇情的程序員關注可第一時間了解更多精彩內容,定期有福利相送喲。 showImg(https://s...
摘要:但是內存空間畢竟有限,隨著我們存儲數據的不斷增長,要緩存的數據量越來越大,當超過了我們的內存大小時,該怎么辦呢解決方法有兩種增加物理內存搭建集群和緩存數據的淘汰機制。增加物理內存簡單粗暴,價格十分昂貴,內存的價格大約是萬元左右。redis 使用的時內存空間來存儲數據的,避免業務應用從后端數據庫中讀取數據,可以提升應用的響應速度。但是內存空間畢竟有限,隨著我們存儲數據的不斷增長,要緩存的數據量...
摘要:哈希的結果應能夠保證原有已分配的內容可以被映射到新的緩沖中去,而不會被映射到舊的緩沖集合中的其他緩沖區。平衡性平衡性是指哈希的結果能夠盡可能分布到所有的緩沖中去,這樣可以使得所有的緩沖空間都得到利用。 memcached分布式原理與實現 標簽(空格分隔): nosql 0x01 概況 1.1 什么是memcached memcached是一個分布式,開源的數據存儲引擎。memcach...
閱讀 2620·2021-10-12 10:12
閱讀 778·2019-08-29 17:25
閱讀 2782·2019-08-29 17:24
閱讀 3207·2019-08-29 17:19
閱讀 1792·2019-08-29 15:39
閱讀 3035·2019-08-26 16:50
閱讀 1984·2019-08-26 12:17
閱讀 2694·2019-08-26 12:16