进程内缓存: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 章节为准。

笔记加载中…