Go語言實戰案例-LRU緩存機制模擬

在高性能服務開發中,緩存是提升訪問速度和減少后端負載的重要手段。常見的緩存淘汰策略中,**LRU(Least Recently Used,最近最少使用)**是應用最廣的一種。本篇我們用Go語言手寫一個LRU緩存機制的模擬實現。


一、LRU緩存機制簡介

1. 定義

LRU緩存是一種固定容量的緩存結構。當緩存已滿時,它會淘汰最近最少使用的那個數據。簡單理解:

誰最久沒被訪問,就先刪除誰。

2. 使用場景

  • ? Web瀏覽器緩存
  • ? 數據庫查詢結果緩存
  • ? 操作系統頁面置換

二、設計要求

LRU緩存應支持以下操作:

  1. 1.?Get(key):如果key存在,返回對應的value,并將該key標記為最近使用;否則返回-1。
  2. 2.?Put(key, value):插入或更新key。如果容量已滿,需要刪除最近最少使用的key。

要求兩種操作都能在?O(1)?時間復雜度內完成。


三、核心數據結構

要實現 O(1) 操作,需要組合以下兩種結構:

1. 哈希表(map)

  • ? 用于存儲?key → 節點?的映射;
  • ? 可在 O(1) 時間內找到節點。

2. 雙向鏈表

  • ? 用于維護數據訪問的順序;
  • ? 頭部表示最近使用,尾部表示最久未使用;
  • ? 插入、刪除節點都是 O(1)。

四、Go語言實現

1. 節點結構

type?Node?struct?{key,?value?intprev,?next?*Node
}

2. LRU緩存結構

type?LRUCache?struct?{capacity?intcache????map[int]*Nodehead?????*Nodetail?????*Node
}
  • ??head?和?tail?是哨兵節點(dummy),方便操作。

3. 初始化

func?Constructor(capacity?int)?LRUCache?{head?:=?&Node{}tail?:=?&Node{}head.next?=?tailtail.prev?=?headreturn?LRUCache{capacity:?capacity,cache:????make(map[int]*Node),head:?????head,tail:?????tail,}
}

4. 輔助方法

//?moveToHead:將節點移動到頭部
func?(l?*LRUCache)?moveToHead(node?*Node)?{l.removeNode(node)l.addToHead(node)
}//?removeNode:刪除鏈表中的節點
func?(l?*LRUCache)?removeNode(node?*Node)?{prev?:=?node.prevnext?:=?node.nextprev.next?=?nextnext.prev?=?prev
}//?addToHead:在頭部插入節點
func?(l?*LRUCache)?addToHead(node?*Node)?{node.prev?=?l.headnode.next?=?l.head.nextl.head.next.prev?=?nodel.head.next?=?node
}//?removeTail:刪除尾部節點并返回它
func?(l?*LRUCache)?removeTail()?*Node?{node?:=?l.tail.prevl.removeNode(node)return?node
}

5. 核心操作

Get
func?(l?*LRUCache)?Get(key?int)?int?{if?node,?ok?:=?l.cache[key];?ok?{l.moveToHead(node)return?node.value}return?-1
}
Put
func?(l?*LRUCache)?Put(key?int,?value?int)?{if?node,?ok?:=?l.cache[key];?ok?{node.value?=?valuel.moveToHead(node)}?else?{newNode?:=?&Node{key:?key,?value:?value}l.cache[key]?=?newNodel.addToHead(newNode)if?len(l.cache)?>?l.capacity?{tail?:=?l.removeTail()delete(l.cache,?tail.key)}}
}

五、完整代碼示例

package?mainimport?"fmt"type?Node?struct?{key,?value?intprev,?next?*Node
}type?LRUCache?struct?{capacity?intcache????map[int]*Nodehead?????*Nodetail?????*Node
}func?Constructor(capacity?int)?LRUCache?{head?:=?&Node{}tail?:=?&Node{}head.next?=?tailtail.prev?=?headreturn?LRUCache{capacity:?capacity,cache:????make(map[int]*Node),head:?????head,tail:?????tail,}
}func?(l?*LRUCache)?Get(key?int)?int?{if?node,?ok?:=?l.cache[key];?ok?{l.moveToHead(node)return?node.value}return?-1
}func?(l?*LRUCache)?Put(key?int,?value?int)?{if?node,?ok?:=?l.cache[key];?ok?{node.value?=?valuel.moveToHead(node)}?else?{newNode?:=?&Node{key:?key,?value:?value}l.cache[key]?=?newNodel.addToHead(newNode)if?len(l.cache)?>?l.capacity?{tail?:=?l.removeTail()delete(l.cache,?tail.key)}}
}func?(l?*LRUCache)?moveToHead(node?*Node)?{l.removeNode(node)l.addToHead(node)
}func?(l?*LRUCache)?removeNode(node?*Node)?{prev?:=?node.prevnext?:=?node.nextprev.next?=?nextnext.prev?=?prev
}func?(l?*LRUCache)?addToHead(node?*Node)?{node.prev?=?l.headnode.next?=?l.head.nextl.head.next.prev?=?nodel.head.next?=?node
}func?(l?*LRUCache)?removeTail()?*Node?{node?:=?l.tail.prevl.removeNode(node)return?node
}func?main()?{cache?:=?Constructor(2)cache.Put(1,?1)cache.Put(2,?2)fmt.Println(cache.Get(1))?//?1cache.Put(3,?3)???????????//?淘汰?key=2fmt.Println(cache.Get(2))?//?-1cache.Put(4,?4)???????????//?淘汰?key=1fmt.Println(cache.Get(1))?//?-1fmt.Println(cache.Get(3))?//?3fmt.Println(cache.Get(4))?//?4
}

六、復雜度分析

  • ??時間復雜度:O(1),Get 和 Put 都只涉及哈希表查找和鏈表操作。
  • ??空間復雜度:O(capacity),存儲固定大小的map和鏈表節點。

七、工程實踐與優化

  1. 1.?線程安全
    在多協程環境中,需使用?sync.Mutex?或?sync.RWMutex?保證安全。
  2. 2.?泛型支持(Go1.18+)
    可以用泛型實現支持任意類型的key/value。
  3. 3.?監控統計
    可增加命中率統計、淘汰計數。

八、應用場景

  • ??數據庫緩存:Redis內部就支持LRU策略;
  • ??瀏覽器緩存:網頁資源加載優化;
  • ??API限速器:存儲用戶最近訪問記錄。

九、總結

  • ? LRU緩存結合了?哈希表?+?雙向鏈表
  • ? 關鍵是?O(1) 時間內完成訪問和淘汰
  • ? 該思想可擴展到 LFU、ARC 等高級緩存策略。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/91029.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/91029.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/91029.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

vue2中實現leader-line-vue連線文章對應字符

效果展示 通過點擊右邊的tag,觸發連接操作 第一步:獲取右邊tag展示 1.右邊的tag列表展示,我這邊是分為兩個list嵌套的數據結構; {"人員": [{

SPEA2(Strength Pareto Evolutionary Algorithm 2)優化算法簡介

前言 提醒: 文章內容為方便作者自己后日復習與查閱而進行的書寫與發布,其中引用內容都會使用鏈接表明出處(如有侵權問題,請及時聯系)。 其中內容多為一次書寫,缺少檢查與訂正,如有問題或其他拓展…

IDEA 手動下載安裝數據庫驅動,IDEA無法下載數據庫驅動問題解決方案,IDEA無法連接數據庫解決方案(通用,Oracle為例)

一、查詢要下載的數據庫驅動 在IDEA側邊欄找到數據庫(databases),新增一個數據連接 右鍵,屬性 點擊下載,查看要下載的驅動版本 二、下載數據庫驅動(Oracle為例) 下載對應MySQL/Oracle數據庫的…

專業Python爬蟲實戰教程:逆向加密接口與驗證碼突破完整案例

案例背景假設我們需要爬取一家內部測試系統的動態數據API接口。該系統前端頁面使用了復雜的JavaScript混淆技術來防止接口被直接調用,同時對請求參數進行了加密簽名。另外,登錄環節帶有圖形驗證碼用于防護。我們的目標是:分析JavaScript代碼&…

【SQL】Windows MySQL 服務查詢啟動停止自啟動(保姆級)

MySQL是一種開放源代碼的輕量級關系型數據庫管理系統,使用最常用的結構化查詢語言(SQL)對數據庫進行管理。由于MySQL具有體積小、速度快、成本低、開放源碼等優點,現已被廣泛應用于互聯網上的中小型網站中,并且大型網站…

算法提升之數論(矩陣+快速冪)

通過矩陣和快速冪的方法來解決算法題目可以很好地降低時間復雜度,幫助大家更好地解決題目。下面這道題目有一定難度,希望大家可以好好地理解,相信對大家會有很大的幫助。問題描述有 n(2≤n≤10) 個玩家玩游戲,他們按 1 到 n 編號。…

數學建模算法-day[14]

6.2 傳染病預測問題 問題提出 世界上存在很多傳染病,如何根據其傳播機理預測疾病得傳染范圍及染病人數等,對傳染病的控制意義十分重大。 1.指數傳播模型 基本假設 (1) 所研究的區域是一封閉區域,在一個時期內人口總量相對穩定,不考…

Linux救援模式之簡介篇

什么是救援模式?救援模式提供了一個最小的Linux環境,通常只加載最基本的系統組件,允許管理員:修復損壞的系統恢復丟失的文件修改配置文件重置密碼檢查磁盤錯誤重新安裝引導加載程序如何進入救援模式?1. 通過GRUB菜單進…

C++20實戰FlamingoIM開發

C++20 與 Flamingo IM 實例 C++20 引入了許多新特性,如概念(Concepts)、協程(Coroutines)、范圍(Ranges)等。Flamingo IM 是一個即時通訊項目,結合 C++20 的特性可以提升代碼的可讀性和性能。以下是基于 C++20 和 Flamingo IM 的實例。 協程實現異步網絡通信 使用 C…

FPGA實現SRIO高速接口與DSP交互,FPGA+DSP異構方案,提供3套工程源碼和技術支持

目錄1、前言:SRIO在FPGADSP架構中的作用工程概述免責聲明2、相關方案推薦我已有的所有工程源碼總目錄----方便你快速找到自己喜歡的項目我這里已有的FPGADSP異構方案我這里已有的 GT 高速接口解決方案3、工程詳細設計方案工程設計原理框圖FPGA端工程源碼FPGA端SRIO從…

記一次導出pdf表單引發的問題

需求:點擊按鈕,將相關內容生成pdf下載下來問題1:之前項目封裝好的下載文件方法不攜帶token 我嘗試新寫了一個方法,攜帶token問題2:此時出現了跨域問題 我分別嘗試在controller類上和方法上加CrossOrigin(origins “*”…

AI-調查研究-39-多模態大模型量化 微調與量化如何協同最大化性能與效率?

點一下關注吧!!!非常感謝!!持續更新!!! 🚀 AI篇持續更新中!(長期更新) AI煉丹日志-30-新發布【1T 萬億】參數量大模型!Kim…

基于Dify構建本地化知識庫智能體:從0到1的實踐指南

技術選型與方案設計 在企業級AI應用落地中,本地化知識庫智能體已成為提升業務效率的核心工具。Dify作為低代碼AI應用開發平臺,結合RAG(檢索增強生成)技術,可快速構建私有化智能問答系統。以下是關鍵技術選型與架構設計…

C++與C#實戰:FFmpeg屏幕錄制開發指南

基于FFmpeg使用C#和C++開發 以下是一些基于FFmpeg使用C#和C++開發的簡單屏幕錄制軟件示例,涵蓋不同平臺和功能需求。這些示例可作為學習或項目開發的起點。 使用C++開發FFmpeg屏幕錄制 基礎屏幕錄制(Windows) #include <libavcodec/avcodec.h> #include <libav…

「源力覺醒 創作者計劃」_DeepseekVS文心一言代碼簡單測試

一起來輕松玩轉文心大模型吧一文心大模型免費下載地址&#xff1a;https://ai.gitcode.com/theme/1939325484087291906小插曲發現自己的上一篇文章的被盜了&#xff0c;而且是在deepseek上檢索資料發現的&#xff0c;最讓我破防的點在于&#xff0c;它完完全全搬運我的文章&…

服務器數據恢復—RAID上層部署的oracle數據庫數據恢復案例

服務器數據恢復環境&故障&#xff1a; 某公司一臺服務器上有一組由24塊FC硬盤組建的raid。 服務器出現故障&#xff0c;無法正常工作。 經過初步檢測&#xff0c;管理員發現導致服務器故障的原因是raid中有兩塊硬盤掉線&#xff0c;導致卷無法掛載。服務器數據恢復過程&…

鏈表迭代翻轉|二分|狀態壓縮bfs|數學

&#x1f36d;lc2039.bfs空閑時間把網絡抽象成圖&#xff0c;用 BFS 算出 0 號節點到各節點的最短距離 d 。結合每個節點發消息的間隔 patience[v] &#xff0c;先算消息往返需要 2d 秒。再看 2d 和 patience[v] 的關系若 2d 能被 patience[v] 整除&#xff0c;最后一條消息已發…

Vulnhub 02-Breakout靶機滲透攻略詳解

一、下載靶機 下載地址&#xff1a;https://download.vulnhub.com/empire/02-Breakout.zip 下載好后使用VM打開&#xff0c;將網絡配置模式改為net&#xff0c;防止橋接其他主機干擾&#xff08;橋接Mac地址也可確定主機&#xff09;。 二、發現主機 使用nmap掃描沒有相應的…

數據結構(5)單鏈表算法題(中)

一、合并兩個有序鏈表 1、題目描述 https://leetcode.cn/problems/merge-two-sorted-lists 2、算法分析 這道題和之前的合并兩個有序數組的思路很像&#xff0c;創建空鏈表即可&#xff0c;可以很輕松地寫出如下代碼。 /*** Definition for singly-linked list.* struct L…

園區網絡搭建實驗

跟著B站上的老師&#xff0c;用華為ensp模擬搭建了一個園區網絡&#xff0c;感覺挺好玩的雖然老師說這個很簡單&#xff0c;但還是比我公司里的拓撲復雜LSW3配置上行端口3/4配置為串口&#xff0c;下行端口1/2為access口用于連接終端[Huawei]vlan batch 10 20 --創建vlan [Hua…