温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

高效Go缓存:HashMap与缓存数据过期自动清理

发布时间:2024-11-09 00:25:37 来源:亿速云 阅读:87 作者:小樊 栏目:编程语言

在Go语言中,实现高效的缓存系统通常需要考虑以下几个方面:

  1. 缓存存储:可以使用map来实现简单的键值对存储。
  2. 缓存过期:需要一种机制来自动清理过期的缓存数据。
  3. 并发安全:在高并发环境下,需要确保缓存的读写操作是线程安全的。

下面是一个简单的示例,展示了如何使用map来实现一个带有过期功能的缓存系统:

package main

import (
	"container/list"
	"fmt"
	"sync"
	"time"
)

// CacheItem 表示缓存项
type CacheItem struct {
	key         string
	value       interface{}
	expiration time.Time
}

// LRUCache 是一个简单的LRU缓存实现
type LRUCache struct {
	capacity int
	cache    map[string]*list.Element
	evictList *list.List
	mu        sync.Mutex
}

// NewLRUCache 创建一个新的LRU缓存
func NewLRUCache(capacity int) *LRUCache {
	return &LRUCache{
		capacity: capacity,
		cache:    make(map[string]*list.Element),
		evictList: list.New(),
	}
}

// Add 添加一个新的缓存项
func (c *LRUCache) Add(key string, value interface{}, ttl time.Duration) {
	c.mu.Lock()
	defer c.mu.Unlock()

	if elem, exists := c.cache[key]; exists {
		c.evictList.MoveToFront(elem)
		elem.Value.(*CacheItem).value = value
		elem.Value.(*CacheItem).expiration = time.Now().Add(ttl)
		return
	}

	if c.evictList.Len() >= c.capacity {
		lastElem := c.evictList.Back()
		delete(c.cache, lastElem.Value.(*CacheItem).key)
		c.evictList.Remove(lastElem)
	}

	item := &CacheItem{
		key:         key,
		value:       value,
		expiration: time.Now().Add(ttl),
	}

	elem := c.evictList.PushFront(item)
	c.cache[key] = elem
}

// Get 获取缓存项,如果不存在则返回nil
func (c *LRUCache) Get(key string) interface{} {
	c.mu.Lock()
	defer c.mu.Unlock()

	if elem, exists := c.cache[key]; exists {
		item := elem.Value.(*CacheItem)
		if time.Now().Before(item.expiration) {
			c.evictList.MoveToFront(elem)
			return item.value
		}
		c.removeElement(elem)
	}
	return nil
}

// removeElement 从链表和缓存中移除元素
func (c *LRUCache) removeElement(elem *list.Element) {
	c.evictList.Remove(elem)
	delete(c.cache, elem.Value.(*CacheItem).key)
}

func main() {
	cache := NewLRUCache(2)

	cache.Add("key1", "value1", 5*time.Second)
	cache.Add("key2", "value2", 10*time.Second)

	fmt.Println(cache.Get("key1")) // 输出: value1

	time.Sleep(6 * time.Second)

	fmt.Println(cache.Get("key1")) // 输出: nil,因为key1已经过期

	cache.Add("key3", "value3", 5*time.Second)

	fmt.Println(cache.Get("key2")) // 输出: nil,因为key2已经被移除
	fmt.Println(cache.Get("key3")) // 输出: value3
}

解释

  1. CacheItem:表示缓存项,包含键、值和过期时间。
  2. LRUCache:实现LRU缓存的结构体,包含容量、缓存映射、过期列表和互斥锁。
  3. NewLRUCache:创建一个新的LRU缓存实例。
  4. Add:添加一个新的缓存项,如果缓存已满则移除最久未使用的项。
  5. Get:获取缓存项,如果存在且未过期则返回值,否则返回nil。
  6. removeElement:从链表和缓存中移除元素。

这个示例展示了如何使用map和双向链表来实现一个简单的LRU缓存,并且具备自动清理过期数据的能力。在高并发环境下,可以考虑使用sync.RWMutex来进一步优化读写性能。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

go
AI