GCache 学习笔记

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. 注意事项

  1. ​内存使用​​:监控缓存内存占用,避免OOM
  2. ​缓存穿透​​:对不存在的键也进行缓存
  3. ​缓存雪崩​​:设置不同的过期时间
  4. ​对象修改​​:缓存对象修改会影响缓存中的值
  5. ​错误处理​​:正确处理LoaderFunc返回的错误

8. 最佳实践

  1. ​键设计​​:
    • 使用简单类型(string, int等)作为键
    • 复杂键先序列化为字符串
  2. ​值设计​​:
    • 使用指针类型存储大对象
    • 考虑使用深拷贝防止意外修改
  3. ​监控​​:
    • 记录缓存命中率
    • 监控缓存大小和性能
  4. ​测试​​:
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. 与其他缓存库对比

特性GCacheGo-CacheBigCache
淘汰策略LRU/LFU/ARC
自动加载
事件监听
高并发性能✅✅
内存效率✅✅

10. 总结

GCache 是一个功能丰富且灵活的 Go 内存缓存库,特别适合需要多种淘汰策略和自动加载功能的场景。通过合理配置和正确使用,可以显著提升应用性能。对于简单的缓存需求,Go-Cache 可能更合适;对于极高并发场景,可以考虑 BigCache。

滚动至顶部