Golang支持TTL的本地缓存实现

在Golang中如何实现支持TTL的本地缓存?希望能找到一个轻量级的解决方案,最好不需要依赖外部存储。具体需求是:

  1. 支持设置键值对的过期时间
  2. 能够自动清理过期的缓存项
  3. 线程安全
  4. 性能较好

有没有推荐的标准库或第三方库可以直接使用?或者需要自己实现的话,有什么需要注意的关键点?

2 回复

推荐使用go-cache库,简单实现带TTL的本地缓存。示例代码:

import "github.com/patrickmn/go-cache"

c := cache.New(5*time.Minute, 10*time.Minute)
c.Set("key", "value", cache.DefaultExpiration)
value, found := c.Get("key")

自动清理过期项目,支持设置默认和自定义过期时间。

更多关于Golang支持TTL的本地缓存实现的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go语言中,实现支持TTL(生存时间)的本地缓存可以通过标准库的sync.Map结合自定义结构体和goroutine来完成。以下是一个简单高效的实现示例:

package main

import (
	"sync"
	"time"
)

type item struct {
	value      interface{}
	expiration int64
}

type Cache struct {
	items *sync.Map
	stop  chan struct{}
}

func NewCache(cleanupInterval time.Duration) *Cache {
	c := &Cache{
		items: &sync.Map{},
		stop:  make(chan struct{}),
	}
	
	// 启动定期清理过期键的goroutine
	go func() {
		ticker := time.NewTicker(cleanupInterval)
		defer ticker.Stop()
		
		for {
			select {
			case <-ticker.C:
				now := time.Now().UnixNano()
				c.items.Range(func(key, value interface{}) bool {
					if item := value.(*item); item.expiration > 0 && now > item.expiration {
						c.items.Delete(key)
					}
					return true
				})
			case <-c.stop:
				return
			}
		}
	}()
	
	return c
}

// Set 存储键值对,并设置TTL
func (c *Cache) Set(key, value interface{}, ttl time.Duration) {
	var exp int64
	if ttl > 0 {
		exp = time.Now().Add(ttl).UnixNano()
	}
	c.items.Store(key, &item{
		value:      value,
		expiration: exp,
	})
}

// Get 获取键对应的值,如果过期或不存在返回nil
func (c *Cache) Get(key interface{}) interface{} {
	val, ok := c.items.Load(key)
	if !ok {
		return nil
	}
	
	item := val.(*item)
	if item.expiration > 0 && time.Now().UnixNano() > item.expiration {
		c.items.Delete(key)
		return nil
	}
	return item.value
}

// Delete 删除指定键
func (c *Cache) Delete(key interface{}) {
	c.items.Delete(key)
}

// Close 停止缓存清理goroutine
func (c *Cache) Close() {
	close(c.stop)
}

使用示例:

func main() {
	cache := NewCache(time.Minute) // 每分钟清理一次过期键
	
	// 设置缓存,TTL为5秒
	cache.Set("key1", "value1", 5*time.Second)
	
	// 立即获取
	if val := cache.Get("key1"); val != nil {
		println(val.(string)) // 输出: value1
	}
	
	// 6秒后获取(已过期)
	time.Sleep(6 * time.Second)
	if val := cache.Get("key1"); val == nil {
		println("key1已过期") // 输出: key1已过期
	}
	
	cache.Close()
}

主要特性:

  1. 使用sync.Map保证并发安全
  2. 后台goroutine定期清理过期数据
  3. 获取时进行过期检查(惰性删除)
  4. 支持无TTL永久存储(设置ttl=0)

注意事项:

  • 适用于单机应用,分布式环境需改用Redis等方案
  • 定期清理间隔需根据业务需求调整
  • 大量数据时注意内存占用

如需更完整功能(如统计、事件回调等),建议使用成熟的第三方库如github.com/patrickmn/go-cache

回到顶部