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 方法,从而无需自行实现锁机制。

相关文章
|
1月前
|
Go
go语言中遍历映射(map)
go语言中遍历映射(map)
46 8
|
2月前
|
存储 缓存 NoSQL
数据的存储--Redis缓存存储(一)
数据的存储--Redis缓存存储(一)
105 1
|
2月前
|
存储 Java API
深入剖析Java Map:不只是存储数据,更是设计艺术的体现!
【10月更文挑战第17天】在Java编程中,Map是一种重要的数据结构,用于存储键值对,并展现了设计艺术的精髓。本文深入剖析了Map的设计原理和使用技巧,包括基本概念、设计艺术(如哈希表与红黑树的空间时间权衡)、以及使用技巧(如选择合适的实现类、避免空指针异常等),帮助读者更好地理解和应用Map。
112 3
|
24天前
|
Go
go语言for遍历映射(map)
go语言for遍历映射(map)
32 12
|
28天前
|
存储 Go
go语言 遍历映射(map)
go语言 遍历映射(map)
34 2
|
1月前
|
缓存 NoSQL PHP
Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出
本文深入探讨了Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出。文章还介绍了Redis在页面缓存、数据缓存和会话缓存等应用场景中的使用,并强调了缓存数据一致性、过期时间设置、容量控制和安全问题的重要性。
43 5
|
1月前
|
存储 缓存 算法
分布式缓存有哪些常用的数据分片算法?
【10月更文挑战第25天】在实际应用中,需要根据具体的业务需求、数据特征以及系统的可扩展性要求等因素综合考虑,选择合适的数据分片算法,以实现分布式缓存的高效运行和数据的合理分布。
|
2月前
|
缓存 监控 前端开发
处理页面缓存中数据不一致的问题
【10月更文挑战第9天】
59 2
|
2月前
|
消息中间件 缓存 NoSQL
大数据-49 Redis 缓存问题中 穿透、雪崩、击穿、数据不一致、HotKey、BigKey
大数据-49 Redis 缓存问题中 穿透、雪崩、击穿、数据不一致、HotKey、BigKey
66 2
|
3月前
|
Go 定位技术 索引
Go 语言Map(集合) | 19
Go 语言Map(集合) | 19