bigcache
是 Go 中一个高性能的本地内存缓存库,专为 大数据量、高并发场景下的缓存需求设计,避免 GC 开销、极致性能优化。适合用于需要快速访问、低延迟、本地缓存的数据。
bigcache
是比map[string]interface{}
更适合做 大量键值对、高并发访问场景的本地缓存。
适用场景 | 描述 |
---|---|
大量缓存键值(数十万级以上) | 内存分片+避免 GC 停顿 |
高并发读写缓存 | 支持每秒上百万级的 R/W |
本地服务缓存热点数据 | 例如:用户会话、文章内容、商品详情 |
不需要分布式缓存 | 无需 Redis,直接驻留内存 |
go get github.com/allegro/bigcache/v3
package main
import (
"fmt"
"time"
"github.com/allegro/bigcache/v3"
)
func main() {
cache, _ := bigcache.NewBigCache(bigcache.DefaultConfig(10 * time.Minute))
// 存值
err := cache.Set("user_123", []byte("张三"))
if err != nil {
panic(err)
}
// 取值
entry, err := cache.Get("user_123")
if err != nil {
fmt.Println("未命中")
} else {
fmt.Println("缓存命中:", string(entry)) // 输出: 张三
}
// 删除(v3+ 支持)
cache.Delete("user_123")
}
config := bigcache.Config{
Shards: 1024, // 并发级别:2^N 个分片
LifeWindow: 5 * time.Minute, // 过期时间
CleanWindow: 1 * time.Minute, // 清理间隔
MaxEntrySize: 512, // 最大 value 大小(字节),防止内存碎片
MaxEntriesInWindow: 1000000, // 预估写入条数
HardMaxCacheSize: 1024, // 最大内存占用(MB)
Verbose: false,
}
cache, _ := bigcache.NewBigCache(config)
[]byte
而非 map[string]interface{}
,避免大对象频繁 GC[]byte
,你需要用 json.Marshal
或 gob
手动序列化对象LifeWindow
批量过期建议封装成一个结构体做序列化:
type CacheStore struct {
cache *bigcache.BigCache
}
func NewCacheStore() *CacheStore {
c, _ := bigcache.NewBigCache(bigcache.DefaultConfig(10 * time.Minute))
return &CacheStore{cache: c}
}
func (c *CacheStore) SetJSON(key string, val interface{}) error {
b, _ := json.Marshal(val)
return c.cache.Set(key, b)
}
func (c *CacheStore) GetJSON(key string, dest interface{}) error {
b, err := c.cache.Get(key)
if err != nil {
return err
}
return json.Unmarshal(b, dest)
}
特性 | map | bigcache | Redis |
---|---|---|---|
并发安全 | ❌ | ✅ | ✅ |
GC 友好 | ❌ | ✅ | ✅ |
支持过期 | ❌ | ✅ | ✅ |
跨进程 | ❌ | ❌ | ✅ |
性能 | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐(网络开销) |
典型用途 | 小量本地缓存 | 高速本地缓存 | 分布式共享缓存 |
下面是一个通用的 BigCacheManager
封装,支持:
cache/
bigcache_manager.go
redis_fallback.go (可选)
bigcache_manager.go
package cache
import (
"encoding/json"
"errors"
"log"
"time"
"github.com/allegro/bigcache/v3"
)
type BigCacheManager struct {
cache *bigcache.BigCache
}
func NewBigCacheManager(defaultTTL time.Duration) (*BigCacheManager, error) {
config := bigcache.Config{
Shards: 1024, // 并发分片数
LifeWindow: defaultTTL,
CleanWindow: 1 * time.Minute,
MaxEntriesInWindow: 1000000,
MaxEntrySize: 1024, // bytes
HardMaxCacheSize: 512, // MB
Verbose: false,
}
cache, err := bigcache.NewBigCache(config)
if err != nil {
return nil, err
}
return &BigCacheManager{cache: cache}, nil
}
// SetJSON - 存入缓存(自动序列化)
func (b *BigCacheManager) SetJSON(key string, val interface{}) error {
data, err := json.Marshal(val)
if err != nil {
return err
}
return b.cache.Set(key, data)
}
// GetJSON - 从缓存读取(自动反序列化)
func (b *BigCacheManager) GetJSON(key string, dest interface{}) error {
data, err := b.cache.Get(key)
if err != nil {
if errors.Is(err, bigcache.ErrEntryNotFound) {
log.Printf("[cache miss] key=%s", key)
return err
}
log.Printf("[cache error] key=%s, err=%v", key, err)
return err
}
return json.Unmarshal(data, dest)
}
// Delete - 删除缓存项
func (b *BigCacheManager) Delete(key string) error {
return b.cache.Delete(key)
}
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
bcm, _ := NewBigCacheManager(10 * time.Minute)
// 写入缓存
user := User{ID: 1, Name: "张三", Age: 28}
bcm.SetJSON("user:1", user)
// 读取缓存
var cachedUser User
err := bcm.GetJSON("user:1", &cachedUser)
if err == nil {
fmt.Printf("缓存命中: %+v\n", cachedUser)
} else {
fmt.Println("缓存未命中")
}
}
你可以扩展成带 Redis fallback 的版本:
type Cache interface {
SetJSON(key string, val interface{}) error
GetJSON(key string, dest interface{}) error
Delete(key string) error
}
然后再实现一个 RedisCacheManager
,并组合调用。
能力 | 说明 |
---|---|
TTL 控制 | 当前为统一 TTL,可按 key 分类扩展 |
Metrics | 接入 Prometheus 记录命中/失败数 |
Namespace 支持 | 加前缀如 user: , item: |
并发加载缓存(如 singleflight) | 防止缓存击穿 |