用 Go 实现一个 LRU cache

简介: 用 Go 实现一个 LRU cache

前言


早在几年前写过关于 LRU cache 的文章:crossoverjie.top/2018/04/07/…


当时是用 Java 实现的,最近我在完善 ptg 时正好需要一个最近最少使用的数据结构来存储历史记录。


ptg: Performance testing tool (Go), 用 Go 实现的 gRPC 客户端调试工具。


Go 官方库中并没有相关的实现,考虑到程序的简洁就不打算依赖第三方库,自己写一个;本身复杂度也不高,没有几行代码。


配合这个数据结构,我便在 ptg 中实现了请求历史记录的功能:


将每次的请求记录存储到 lru cache 中,最近使用到的历史记录排在靠前,同时也能提供相关的搜索功能;具体可见下图。


网络异常,图片无法展示
|


实现


网络异常,图片无法展示
|


实现原理没什么好说的,和 Java 的一样:


  • 一个双向链表存储数据的顺序


  • 一个 map 存储最终的数据


  • 当数据达到上限时移除链表尾部数据


  • 将使用到的 Node 移动到链表的头结点


虽然 Go 比较简洁,但好消息是基本的双向链表结构还是具备的。


网络异常,图片无法展示
|


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


网络异常,图片无法展示
|


根据之前的分析:


  • size 存储缓存大小。


  • 链表存储数据顺序。


  • map 存储数据。


  • lock 用于控制并发安全。


网络异常,图片无法展示
|


网络异常,图片无法展示
|


接下来重点是两个函数:写入、查询。


写入时判断是否达到容量上限,达到后删除尾部数据;否则就想数据写入头部。


而获取数据时,这会将查询到的结点移动到头结点。


这些结点操作都由 List 封装好了的。


网络异常,图片无法展示
|


所以使用起来也比较方便。


最终就是通过这个 LruCache 实现了上图的效果,想要了解更多细节的可以参考源码:


github.com/crossoverJi…


相关文章
|
存储 缓存 NoSQL
一文搞懂Go整合captcha实现验证码功能
一文搞懂Go整合captcha实现验证码功能
|
XML JSON Java
RPC框架之Thrift—实现Go和Java远程过程调用
RPC框架之Thrift—实现Go和Java远程过程调用
|
监控 测试技术 Go
用 Go 从零实现日志包 - 第零篇 序言
设计一个日志包,需要考虑的基础功能有日志级别设置、标准输出和文件、输出格式配置、日志的时间戳、文件与打印行号、正文。高级功能有按级别分类输出、支持结构化日志、支持日志轮转。
138 0
|
Go 数据安全/隐私保护
Go 实现 AES 加密 CBC 模式|Go主题月
密码分组链接模式 CBC (Cipher Block Chaining),这种模式是先将明文切分成若干小段,然后每一小段与初始块或者上一段的密文段进行异或运算后,再与密钥进行加密。
362 0
|
Go
【Golang】panic和recover底层逻辑实现|Go主题月
在每个goroutine也有一个指针指向_panic链表表头,然后每增加一个panic就会在链表头部加入一个_panic结构体。当所有的defer执行完后,_panic链表就会从尾部开始打印panic信息了,也就是说先发生的panic先打印信息。
243 0
go语言实现【队列】|二叉树的【先序遍历】【创建】
go语言实现【队列】|二叉树的【先序遍历】【创建】
go语言实现【队列】|二叉树的【先序遍历】【创建】
Go整合Logrus实现日志打印
Go整合Logrus实现日志打印
|
SQL Prometheus Cloud Native
Go整合gorm实现CRUD
Go整合gorm实现CRUD
|
存储 安全 Go
Go源码解读-sync.Map的实现
Go源码解读-sync.Map的实现
136 0