Golang内存缓存实现与优化指南
Golang内存缓存实现与优化指南 我正在尝试实现内存缓存。有哪些可能的方法可以实现它?有哪些最佳的三方包可用,或者使用内置功能来构建它是否更可取? 我还有一个疑问,memcache 和内存缓存是相同的还是完全不同的?
2 回复
sync package - sync - Go Packages
sync 包提供了基本的同步原语,例如互斥锁。
GitHub - Karl1b/cachetest
通过在 GitHub 上创建一个帐户来为 Karl1b/cachetest 开发做出贡献。
更多关于Golang内存缓存实现与优化指南的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go中实现内存缓存有多种方式,以下是几种主要方法:
1. 使用内置的sync.Map(适用于读多写少场景)
package main
import (
"sync"
"time"
)
type CacheItem struct {
Value interface{}
Expiration int64
}
type MemoryCache struct {
items sync.Map
mu sync.RWMutex
}
func NewMemoryCache() *MemoryCache {
return &MemoryCache{}
}
func (c *MemoryCache) Set(key string, value interface{}, ttl time.Duration) {
expiration := time.Now().Add(ttl).UnixNano()
c.items.Store(key, CacheItem{
Value: value,
Expiration: expiration,
})
}
func (c *MemoryCache) Get(key string) (interface{}, bool) {
item, found := c.items.Load(key)
if !found {
return nil, false
}
cacheItem := item.(CacheItem)
if time.Now().UnixNano() > cacheItem.Expiration {
c.items.Delete(key)
return nil, false
}
return cacheItem.Value, true
}
2. 使用map + sync.RWMutex(更精细的控制)
type RWCache struct {
items map[string]CacheItem
mu sync.RWMutex
}
func NewRWCache() *RWCache {
return &RWCache{
items: make(map[string]CacheItem),
}
}
func (c *RWCache) Set(key string, value interface{}, ttl time.Duration) {
c.mu.Lock()
defer c.mu.Unlock()
c.items[key] = CacheItem{
Value: value,
Expiration: time.Now().Add(ttl).UnixNano(),
}
}
func (c *RWCache) Get(key string) (interface{}, bool) {
c.mu.RLock()
item, found := c.items[key]
c.mu.RUnlock()
if !found {
return nil, false
}
if time.Now().UnixNano() > item.Expiration {
c.mu.Lock()
delete(c.items, key)
c.mu.Unlock()
return nil, false
}
return item.Value, true
}
3. 流行的第三方包
go-cache(最常用)
import (
"github.com/patrickmn/go-cache"
"time"
)
func main() {
// 创建缓存,默认过期时间5分钟,清理间隔10分钟
c := cache.New(5*time.Minute, 10*time.Minute)
// 设置缓存
c.Set("key", "value", cache.DefaultExpiration)
// 获取缓存
if x, found := c.Get("key"); found {
fmt.Println(x)
}
// 带过期时间的设置
c.Set("foo", "bar", 30*time.Second)
}
bigcache(高性能,适用于大量数据)
import "github.com/allegro/bigcache"
func main() {
config := bigcache.Config{
Shards: 1024,
LifeWindow: 10 * time.Minute,
CleanWindow: 5 * time.Minute,
MaxEntriesInWindow: 1000 * 10 * 60,
MaxEntrySize: 500,
Verbose: true,
}
cache, _ := bigcache.NewBigCache(config)
cache.Set("key", []byte("value"))
entry, _ := cache.Get("key")
fmt.Println(string(entry))
}
ristretto(高性能,高命中率)
import "github.com/dgraph-io/ristretto"
func main() {
cache, _ := ristretto.NewCache(&ristretto.Config{
NumCounters: 1e7, // 键跟踪数量
MaxCost: 1 << 30, // 最大成本(字节)
BufferItems: 64, // 缓冲区大小
})
cache.Set("key", "value", 1)
cache.Wait()
if value, found := cache.Get("key"); found {
fmt.Println(value)
}
}
4. 关于memcache与内存缓存的区别
memcache(通常指Memcached)和内存缓存是不同的:
内存缓存(In-memory Cache):
- 应用程序进程内的缓存
- 零网络延迟
- 数据与应用程序生命周期相同(重启丢失)
- 示例:go-cache, bigcache, ristretto
Memcached:
- 独立的内存缓存服务器
- 需要网络访问
- 分布式支持
- 数据持久于独立服务
- Go客户端:
github.com/bradfitz/gomemcache
// Memcached使用示例
import "github.com/bradfitz/gomemcache/memcache"
func main() {
mc := memcache.New("localhost:11211")
mc.Set(&memcache.Item{Key: "key", Value: []byte("value")})
item, _ := mc.Get("key")
fmt.Println(string(item.Value))
}
5. 性能优化建议
// 使用字节切片而非接口{}减少分配
type ByteCache struct {
items map[string][]byte
mu sync.RWMutex
}
// 批量操作减少锁竞争
func (c *ByteCache) MultiSet(items map[string][]byte) {
c.mu.Lock()
defer c.mu.Unlock()
for k, v := range items {
c.items[k] = v
}
}
// 使用对象池重用对象
var itemPool = sync.Pool{
New: func() interface{} {
return make([]byte, 0, 1024)
},
}
选择方案:
- 简单场景:go-cache
- 高性能需求:ristretto或bigcache
- 分布式需求:Memcached或Redis
- 最小依赖:内置sync.Map或map+mutex

