1. GCache 简介
GCache 是一个 Go 语言实现的高性能内存缓存库,具有以下特点:
- 支持多种缓存淘汰策略:LRU、LFU、ARC
- 线程安全,支持并发访问
- 支持缓存加载函数(自动填充)
- 可设置缓存大小限制和过期时间
- 简单的 API 设计
2. 基本使用
2.1 安装
go get -u github.com/bluele/gcache
2.2 创建缓存实例
import "github.com/bluele/gcache"
// 创建LRU缓存,容量100
cache := gcache.New(100).
LRU().
Build()
// 创建带过期时间的缓存(10分钟)
cache := gcache.New(100).
LRU().
Expiration(10 * time.Minute).
Build()
2.3 基本操作
// 设置值
cache.Set("key1", "value1")
// 获取值
value, err := cache.Get("key1")
if err == nil {
fmt.Println(value)
}
// 删除键
cache.Remove("key1")
// 清空缓存
cache.Purge()
3. 缓存淘汰策略
GCache 支持三种淘汰策略:
3.1 LRU (Least Recently Used)
cache := gcache.New(100).
LRU().
Build()
- 淘汰最近最少使用的项目
- 适合大多数通用场景
3.2 LFU (Least Frequently Used)
cache := gcache.New(100).
LFU().
Build()
- 淘汰使用频率最低的项目
- 适合长期热点数据场景
3.3 ARC (Adaptive Replacement Cache)
cache := gcache.New(100).
ARC().
Build()
- 自适应替换算法,结合LRU和LFU优点
- 适合访问模式变化较大的场景
4. 高级功能
4.1 自动填充缓存
cache := gcache.New(100).
LRU().
LoaderFunc(func(key interface{}) (interface{}, error) {
// 当缓存未命中时自动调用此函数加载数据
return fmt.Sprintf("value-for-%v", key), nil
}).
Build()
// 自动加载数据
value, err := cache.Get("key1")
4.2 过期时间设置
cache := gcache.New(100).
LRU().
Expiration(10 * time.Minute). // 全局过期时间
Build()
// 为单个键设置特定过期时间
cache.SetWithExpire("key1", "value1", 5 * time.Minute)
4.3 事件监听
cache := gcache.New(100).
LRU().
AddedFunc(func(key, value interface{}) {
fmt.Printf("Added: %v=%v\n", key, value)
}).
EvictedFunc(func(key, value interface{}) {
fmt.Printf("Evicted: %v=%v\n", key, value)
}).
Build()
5. 性能优化
5.1 容量设置
// 根据应用需求设置合理容量
cache := gcache.New(calculateAppropriateSize()).
LRU().
Build()
5.2 避免大对象
// 大对象考虑拆分为多个小对象存储
type BigData struct {
Part1 []byte
Part2 []byte
}
5.3 批量操作
// 批量设置提高性能
items := map[interface{}]interface{}{
"key1": "value1",
"key2": "value2",
}
cache.SetAll(items)
6. 使用示例
6.1 HTTP 响应缓存
var responseCache gcache.Cache
func init() {
responseCache = gcache.New(1000).
LRU().
Expiration(5 * time.Minute).
Build()
}
func handler(w http.ResponseWriter, r *http.Request) {
cacheKey := r.URL.Path
// 尝试从缓存获取
if cached, err := responseCache.Get(cacheKey); err == nil {
w.Write(cached.([]byte))
return
}
// 生成响应
response := generateResponse(r)
// 存入缓存
responseCache.Set(cacheKey, response)
w.Write(response)
}
6.2 数据库查询缓存
type UserCache struct {
cache gcache.Cache
db *gorm.DB
}
func NewUserCache(db *gorm.DB) *UserCache {
return &UserCache{
cache: gcache.New(500).
ARC().
Expiration(30 * time.Minute).
LoaderFunc(func(key interface{}) (interface{}, error) {
var user User
if err := db.First(&user, key).Error; err != nil {
return nil, err
}
return &user, nil
}).
Build(),
db: db,
}
}
func (uc *UserCache) GetUser(id uint) (*User, error) {
value, err := uc.cache.Get(id)
if err != nil {
return nil, err
}
return value.(*User), nil
}
7. 注意事项
- 内存使用:监控缓存内存占用,避免OOM
- 缓存穿透:对不存在的键也进行缓存
- 缓存雪崩:设置不同的过期时间
- 对象修改:缓存对象修改会影响缓存中的值
- 错误处理:正确处理LoaderFunc返回的错误
8. 最佳实践
- 键设计:
- 使用简单类型(string, int等)作为键
- 复杂键先序列化为字符串
- 值设计:
- 使用指针类型存储大对象
- 考虑使用深拷贝防止意外修改
- 监控:
- 记录缓存命中率
- 监控缓存大小和性能
- 测试:
func TestCacheEviction(t *testing.T) {
cache := gcache.New(2).LRU().Build()
cache.Set("k1", "v1")
cache.Set("k2", "v2")
cache.Set("k3", "v3") // k1 should be evicted
_, err := cache.Get("k1")
if err != gcache.KeyNotFoundError {
t.Error("LRU eviction failed")
}
}
9. 与其他缓存库对比
| 特性 | GCache | Go-Cache | BigCache |
|---|---|---|---|
| 淘汰策略 | LRU/LFU/ARC | 无 | 无 |
| 自动加载 | ✅ | ❌ | ❌ |
| 事件监听 | ✅ | ❌ | ❌ |
| 高并发性能 | ✅ | ✅ | ✅✅ |
| 内存效率 | ✅ | ✅ | ✅✅ |
10. 总结
GCache 是一个功能丰富且灵活的 Go 内存缓存库,特别适合需要多种淘汰策略和自动加载功能的场景。通过合理配置和正确使用,可以显著提升应用性能。对于简单的缓存需求,Go-Cache 可能更合适;对于极高并发场景,可以考虑 BigCache。



