用 Go 实现一个 LRU cache

前言
早在几年前写过关于 LRU cache 的文章:
https://crossoverjie.top/2018/04/07/algorithm/LRU-cache/
当时是用 Java 实现的,最近我在完善 ptg 时正好需要一个最近最少使用的数据结构来存储历史记录。
ptg: Performance testing tool (Go), 用 Go 实现的 gRPC 客户端调试工具。
Go 官方库中并没有相关的实现,考虑到程序的简洁就不打算依赖第三方库,自己写一个;本身复杂度也不高,没有几行代码。
配合这个数据结构,我便在 ptg 中实现了请求历史记录的功能:
将每次的请求记录存储到 lru cache 中,最近使用到的历史记录排在靠前,同时也能提供相关的搜索功能;具体可见下图。

实现

实现原理没什么好说的,和 Java 的一样:
- 一个双向链表存储数据的顺序
- 一个
map存储最终的数据 - 当数据达到上限时移除链表尾部数据
- 将使用到的
Node移动到链表的头结点
虽然 Go 比较简洁,但好消息是基本的双向链表结构还是具备的。

所以基于此便定义了一个 LruCache:

根据之前的分析:
size存储缓存大小。- 链表存储数据顺序。
map存储数据。lock用于控制并发安全。

接下来重点是两个函数:写入、查询。
写入时判断是否达到容量上限,达到后删除尾部数据;否则就想数据写入头部。
而获取数据时,这会将查询到的结点移动到头结点。
这些结点操作都由 List 封装好了的。

所以使用起来也比较方便。
最终就是通过这个 LruCache 实现了上图的效果,想要了解更多细节的可以参考源码:
https://github.com/crossoverJie/ptg/blob/main/gui/lru.go
用 Go 实现一个 LRU cache的更多相关文章
- 如何设计一个LRU Cache
如何设计一个LRU Cache? Google和百度的面试题都出现了设计一个Cache的题目,什么是Cache,如何设计简单的Cache,通过搜集资料,本文给出个总结. 通常的问题描述可以是这样: Q ...
- [转]如何用C++实现一个LRU Cache
[转自http://hawstein.com/posts/lru-cache-impl.html] LRU是Least Recently Used的缩写,意思是最近最少使用,它是一种Cache替换算法 ...
- 设计并实现一个LRU Cache
一.什么是Cache 1 概念 Cache,即高速缓存,是介于CPU和内存之间的高速小容量存储器.在金字塔式存储体系中它位于自顶向下的第二层,仅次于CPU寄存器.其容量远小于内存,但速度却可以接近CP ...
- 动手实现一个 LRU cache
前言 LRU 是 Least Recently Used 的简写,字面意思则是最近最少使用. 通常用于缓存的淘汰策略实现,由于缓存的内存非常宝贵,所以需要根据某种规则来剔除数据保证内存不被撑满. 如常 ...
- LRU Cache
LRU Cache 题目链接:https://oj.leetcode.com/problems/lru-cache/ Design and implement a data structure for ...
- 【leetcode刷题笔记】LRU Cache
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the fol ...
- 【Leetcode146】LRU Cache
问题描述: 设计一个LRU Cache . LRU cache 有两个操作函数. 1.get(key). 返回cache 中的key对应的 val 值: 2.set(key, value). 用伪代码 ...
- Redis(八) LRU Cache
Redis(八)-- LRU Cache 在计算机中缓存可谓无所不在,无论还是应用还是操作系统中,为了性能都需要做缓存.然缓存必然与缓存算法息息相关,LRU就是其中之一.笔者在最先接触LRU是大学学习 ...
- [LeetCode] LRU Cache 最近最少使用页面置换缓存器
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the fol ...
随机推荐
- 应用SpringAOP及Tlog工具完成日志链路追踪、收集、持久化
一.痛点 目前我司各系统的日志管理比较原始,使用logback打日志到log文件,虽然有服务管理平台,但记录的日志也仅仅是前置机调用后台系统的出入参,当遇到问题时查日志较为麻烦. 登录VPN-打开服务 ...
- 关于 RocketMQ ClientID 相同引发的消息堆积的问题
首先,造成这个问题的 BUG RocketMQ 官方已经在 3月16号 的这个提交中修复了,这里只是探讨一下在修复之前造成问题的具体细节,更多的上下文可以参考我之前写的 <RocketMQ Co ...
- 基于CarbonData的电信时空大数据探索
摘要:作为IOT最底层的无线通信网络生成大量与位置相关的数据,用于无线通信网络规划和优化,帮助电信运营商建设更好体验的精品网络,构建万物互联的信息社会. 本文分享自华为云社区<基于CarbonD ...
- 互联网java面试宝典
1.为什么使用消息队列啊? 答题: 消息队列的核心功能就是:解耦合,异步,流量削峰解耦:接口调用发送,那如果E系统也要这个数据呢?那如果C系统现在不需要了呢?现在A系统又要发送第二种数据了呢?A系统负 ...
- CentOS7部署ceph
CEPH 简介 不管你是想为云平台提供Ceph 对象存储和/或 Ceph 块设备,还是想部署一个 Ceph 文件系统或者把 Ceph 作为他用,所有 Ceph 存储集群的部署都始于部署一个个 Ceph ...
- [NOI2020] 超现实树
我们定义链树为:在该树上的任意节点,左右子树大小的最小值小于2. 举个例子: 那么我们思考,链树显然可以在叶子节点任意替换成其他子树. 那么在主链上,我们可以做到生成任意深度大于主链长度的树. 反过来 ...
- Codeforces 986E - Prince's Problem(树上前缀和)
题面传送门 题意: 有一棵 \(n\) 个节点的树,点上有点权 \(a_i\),\(q\) 组询问,每次询问给出 \(u,v,w\),要求: \(\prod\limits_{x\in P(u,v)}\ ...
- Codeforces 889E - Mod Mod Mod(dp+状态设计)
Codeforces 题目传送门 & 洛谷题目传送门 题目名称 hopping 我们记 \(x_i=X\bmod a_1\bmod a_2\bmod\dots\bmod a_i\),也就是 \ ...
- Codeforces 1303G - Sum of Prefix Sums(李超线段树+点分治)
Codeforces 题面传送门 & 洛谷题面传送门 个人感觉这题称不上毒瘤. 首先看到选一条路径之类的字眼可以轻松想到点分治,也就是我们每次取原树的重心 \(r\) 并将路径分为经过重心和不 ...
- 洛谷 P3270 - [JLOI2016]成绩比较(容斥原理+组合数学+拉格朗日插值)
题面传送门 考虑容斥.我们记 \(a_i\) 为钦定 \(i\) 个人被 B 神碾压的方案数,如果我们已经求出了 \(a_i\) 那么一遍二项式反演即可求出答案,即 \(ans=\sum\limits ...