进程内缓存:gcache 用法、过期时间与 LRU 选项
引言
高频读取、低频变化的数据(配置、字典、热点列表)放进程内缓存最划算。gcache 是 GoFrame 自带的缓存组件,默认提供内存缓存实现,单机部署开箱即用。
概念
- 缓存对象:
gcache.New()创建独立缓存;gcache 包级别的方法(gcache.Set/Get等)操作一个共享的默认缓存实例。 - 写入与过期:
Set(ctx, key, value, duration),duration为过期时长;传0表示永不过期,过期后自动失效。 - 读取:
Get(ctx, key)返回*gvar.Var,未命中为空值;MustGet等便捷方法可配合使用。 - 防击穿:
GetOrSetFunc在缓存未命中时执行给定函数回填数据,常用于热点数据加载。 - 容量与淘汰:内存缓存支持容量上限与 LRU 淘汰等选项(初始化或写入时的相关选项字段以官方文档 gcache 章节为准)。
- 注意:gcache 是进程内缓存,多实例部署时各实例数据独立;需要共享缓存请改用 Redis。
代码示例
基本使用:
package main
import (
"context"
"fmt"
"time"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcache"
"github.com/gogf/gf/v2/os/gctx"
)
func main() {
ctx := gctx.New()
// 1. 使用默认缓存实例(包级方法)
err := gcache.Set(ctx, "k1", "v1", time.Minute) // 1 分钟过期
if err != nil {
panic(err)
}
v, err := gcache.Get(ctx, "k1")
if err != nil {
panic(err)
}
fmt.Println("k1 =", v.String())
// 2. 永不过期:duration 传 0
_ = gcache.Set(ctx, "k2", 100, 0)
// 3. 缓存未命中时回填(防击穿写法)
// 数据源函数:模拟从数据库读取
loadFromDB := func(ctx context.Context) (interface{}, error) {
return "db-value", nil
}
val, err := gcache.GetOrSetFunc(ctx, "hot:key", loadFromDB, 5*time.Minute)
if err != nil {
panic(err)
}
fmt.Println("hot:key =", val.String())
// 4. 判断存在与删除
exists, _ := gcache.Contains(ctx, "k2")
fmt.Println("contains k2:", exists)
_, err = gcache.Remove(ctx, "k2")
if err != nil {
panic(err)
}
size, _ := gcache.Size(ctx)
fmt.Println("cache size =", size)
}
创建独立缓存实例(不同业务隔离):
cache := gcache.New()
_ = cache.Set(ctx, "token", "abc", 30*time.Minute)
v, _ := cache.Get(ctx, "token")
fmt.Println("token =", v.String())
如果需要限制缓存容量并启用 LRU 淘汰,可在创建/写入时指定容量与淘汰选项(具体字段名以官方文档为准):
// 示例:创建带容量上限的缓存(选项写法见官方文档)
// cache := gcache.New(gcache.SetAdapterMemory(gcache.NewAdapterMemory(...)))
// _ = cache.Set(ctx, "k", "v", 0, gcache.SetOption{...}) // LRU 相关选项
注意点
- gcache 的 key 类型为
interface{},但实践中建议统一用字符串,避免类型不一致导致的未命中。 - 值为
gvar.Var包装,读取后调用.String()/.Int()等转换;未命中时空值不等于nil,判断用IsEmpty()或先Contains。 - 过期只是逻辑上的"读不到",数据仍在内存中由内部清理机制回收;对内存极其敏感的场景关注容量选项。
- 多进程/多实例部署时慎用 gcache 存强一致数据。
小结
Set/Get 加过期时间即可用起来,GetOrSetFunc 防击穿,容量与 LRU 选项按需开启。数据要跨实例共享时再考虑 Redis(第 19 章)。选项与淘汰机制细节以官方文档 goframe.org 的 gcache 章节为准。