Go 中使用 map 实现高效的数据缓存

简介: Go 中使用 map 实现高效的数据缓存

在 Go 语言中,使用 map 结合 LRU(Least Recently Used) 缓存算法,可以实现高效的数据缓存。以下是一个示例实现:

import (
    "container/list"
    "sync"
)

type Cache struct {
   
    capacity int
    mu       sync.Mutex
    list     *list.List
    m        map[string]*list.Element
}

type entry struct {
   
    key   string
    value interface{
   }
}

func NewCache(capacity int) *Cache {
   
    return &Cache{
   
        capacity: capacity,
        list:     list.New(),
        m:        make(map[string]*list.Element, capacity),
    }
}

func (c *Cache) Get(key string) (value interface{
   }, ok bool) {
   
    c.mu.Lock()
    defer c.mu.Unlock()

    if elem, ok := c.m[key]; ok {
   
        c.list.MoveToFront(elem)
        return elem.Value.(*entry).value, true
    }
    return nil, false
}

func (c *Cache) Put(key string, value interface{
   }) {
   
    c.mu.Lock()
    defer c.mu.Unlock()

    if elem, ok := c.m[key]; ok {
   
        c.list.MoveToFront(elem)
        elem.Value.(*entry).value = value
        return
    }

    if c.list.Len() == c.capacity {
   
        old := c.list.Back()
        c.list.Remove(old)
        delete(c.m, old.Value.(*entry).key)
    }

    elem := c.list.PushFront(&entry{
   key, value})
    c.m[key] = elem
}

这个缓存实现使用了 sync.Mutex 来确保线程安全,并使用 container/list 包中的双向链表来维护 LRU 顺序。

主要流程如下:

  1. Get(key) 方法先获取读锁,然后在 map 中查找键对应的值。如果找到,则将对应的链表节点移到链表头部,并返回值。
  2. Put(key, value) 方法先获取写锁,然后在 map 中查找键是否存在:
    • 如果存在,则将对应的链表节点移到链表头部,并更新值。
    • 如果不存在且缓存已满,则删除链表末尾的节点及其在 map 中的记录,然后添加新的节点到链表头部。

这种结构可以提供 O(1) 时间复杂度的 GetPut 操作,并能自动淘汰最久未使用的数据,非常适用于缓存场景。

此外,您也可以使用 Go 标准库中的 sync.Map 类型,它自带了并发安全的 LoadStoreDelete 方法,从而无需自行实现锁机制。

相关文章
|
10天前
|
存储 安全 测试技术
【Go语言精进之路】构建高效Go程序:了解map实现原理并高效使用
【Go语言精进之路】构建高效Go程序:了解map实现原理并高效使用
25 3
|
2天前
|
Go
go语言map、实现set
go语言map、实现set
9 0
|
7天前
|
存储 缓存 安全
Go 中使用 map 实现高效的数据查找和更新
Go 中使用 map 实现高效的数据查找和更新
|
2天前
|
Go
go切片和map比较
go切片和map比较
6 0
|
17天前
|
JSON Go 数据格式
Go 语言基础之指针、复合类型【数组、切片、指针、map、struct】(4)
Go 语言基础之指针、复合类型【数组、切片、指针、map、struct】
|
17天前
|
Java 编译器 Go
Go 语言基础之指针、复合类型【数组、切片、指针、map、struct】(3)
Go 语言基础之指针、复合类型【数组、切片、指针、map、struct】
|
Go 调度 负载均衡
如何用GO每秒处理100万条数据请求
最近看了一篇文章,用go处理每分钟达百万条的数据请求原文地址:http://marcio.io/2015/07/handling-1-million-requests-per-minute-with-golang/翻译地址:https://www.jianshu.com/p/21de03ac682c 这里作者为处理高峰期高并发的数据请求,用了3个版本的处理方式,下面是自己的一些理解: 第一种方式很简单,就是用go的协程处理请求,来一条请求开一个协程处理,由于每个请求是一个数据上传任务,有一定的耗时和资源消耗,当高峰期请求突然增多达到每分钟百万条的时候,不可避免的造成了携程爆炸,系统崩溃。
1929 0
|
5天前
|
安全 测试技术 Go
Go语言在高并发场景下的应用
在当今互联网高速发展的时代,高并发已成为众多应用系统面临的核心问题。本文探讨了Go语言在高并发场景下的优势,并通过具体实例展示了其在实际应用中的效果和性能表现。
|
2天前
|
Go
go语言数组与切片
go语言数组与切片
10 0
|
5天前
|
存储 中间件 Go
在go语言服务中封装路由和示例
【6月更文挑战第23天】本文介绍golang后端按协议处理、中间件(一次性与每次请求执行)划分、以及服务架构Controller、Logic/Service、DAO/Repository和Routers划分。代码仓库在GitHub上提供。使用框架简化了交互和处理。后续章节深入探讨服务构建。
104 5
在go语言服务中封装路由和示例