关于 golang-samber-hot
面向 Go 工程师的 samber/hot 缓存使用技能,介绍 Go 1.22+ 的泛型内存缓存及其配置。内容涵盖淘汰策略、过期、加载器、分片和指标监控。
主要功能
- 019 种缓存淘汰算法
- 02TTL 与过期清理
- 03带 singleflight 去重的加载器
- 04分片与过期时重新验证
- 05Prometheus 指标
适用场景
- 01按访问模式选择淘汰算法
- 02缓存数据库读取并合并并发加载
- 03通过 TTL 与抖动管理过期
- 04监控缓存命中率并调整容量
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ samber/ cc-skills-golang --skill golang-samber-hot安装后在 Claude Code 中输入/golang-samber-hot确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
evals/evals.jsonreferences/algorithm-guide.mdapi-reference.mdproduction-patterns.md详细介绍
**角色:**你是一名 Go 工程师,将缓存视为系统设计决策。你会根据实测的访问模式选择淘汰算法,根据工作集数据确定缓存大小,并始终考虑过期处理、加载器失败和监控。
在 Go 中使用 samber/hot 进行内存缓存
适用于 Go 1.22+ 的泛型、类型安全内存缓存库,支持 9 种淘汰算法、TTL、带有 singleflight 去重的加载器链、分片、stale-while-revalidate 和 Prometheus 指标。
官方资源:
本技能并未涵盖所有内容——更多信息请参阅库文档和代码示例:
- 有关 Go 包文档、符号、版本、导入方和已知漏洞,→ 请参阅
samber/cc-skills-golang@golang-pkg-go-dev技能(godig);查询 Go 包信息时优先使用它,而非 Context7。 - 要在自己的代码中查找此库的用法(定义、调用点、诊断),→ 请参阅
samber/cc-skills-golang@golang-gopls技能(gopls)。 - 对于未收录到 pkg.go.dev 的文档,Context7 仍可作为备用方案。
go get -u github.com/samber/hot
算法选择
根据访问模式进行选择——选错算法会浪费内存或大幅降低命中率。
| 算法 | 常量 | 最适合 | 应避免的情况 |
|---|---|---|---|
| W-TinyLFU | hot.WTinyLFU | 通用、混合工作负载(默认) | 需要便于调试的简单算法 |
| LRU | hot.LRU | 由近期访问主导(会话、近期查询) | 频率很重要(扫描污染会淘汰热点条目) |
| LFU | hot.LFU | 由访问频率主导(热门产品、DNS) | 访问模式会变化(过时的热门条目始终无法淘汰) |
| TinyLFU | hot.TinyLFU | 读取密集且偏重访问频率 | 写入密集(准入过滤器开销较大) |
| S3FIFO | hot.S3FIFO | 高吞吐量、抗扫描 | 小型缓存(<1000 个条目) |
| ARC | hot.ARC | 自动调优、模式未知 | 内存受限(跟踪开销为 2 倍) |
| TwoQueue | hot.TwoQueue | 热/冷分区的混合工作负载 | 无法接受调优的复杂性 |
| SIEVE | hot.SIEVE | 简单且抗扫描的 LRU 替代方案 | 访问模式高度倾斜 |
| FIFO | hot.FIFO | 简单、可预测的淘汰顺序 | 命中率很重要(不考虑频率或近期访问) |
**快速决策:**从 hot.WTinyLFU 开始。只有当性能分析表明未命中率过高、无法满足 SLO 时,才进行切换。
算法详细对比、基准测试和决策树,请参阅算法指南。
核心用法
带 TTL 的基本缓存
import "github.com/samber/hot"
cache := hot.NewHotCache[string, *User](hot.WTinyLFU, 10_000).
WithTTL(5 * time.Minute).
WithJanitor().
Build()
defer cache.StopJanitor()
cache.Set("user:123", user)
cache.SetWithTTL("session:abc", session, 30*time.Minute)
value, found, err := cache.Get("user:123")
加载器模式(读穿透)
加载器会自动获取缺失的键,并通过 singleflight 去重——针对同一个缺失键的并发 Get() 调用会共享一次加载器调用:
cache := hot.NewHotCache[int, *User](hot.WTinyLFU, 10_000).
WithTTL(5 * time.Minute).
WithLoaders(func(ids []int) (map[int]*User, error) {
return db.GetUsersByIDs(ctx, ids) // batch query
}).
WithJanitor().
Build()
defer cache.StopJanitor()
user, found, err := cache.Get(123) // triggers loader on miss
容量规划
设置缓存容量前,请估算内存预算可以容纳多少条目:
- 估算单条目大小——估算结构体的大小,并加上堆上分配的字段(切片、映射、字符串)的大小。还要计入键的大小。每个条目的内部管理开销约为 100 字节,可粗略覆盖内部簿记所需空间(指针、过期时间戳、算法元数据)。
- 询问开发者生产环境中为此缓存分配了多少内存(例如,256 MB、1 GB)。这取决于服务的总内存以及进程中其他共享资源的情况。
- 计算容量——
capacity = memoryBudget / estimatedItemSize。向下取整,为额外开销留出空间。
Example: *User struct ~500 bytes + string key ~50 bytes + overhead ~100 bytes = ~650 bytes/entry
256 MB budget → 256_000_000 / 650 ≈ 393,000 items
如果条目大小未知,请让开发者通过单元测试进行测量:分配 N 个条目并检查 runtime.ReadMemStats。不经测量就猜测容量,会导致 OOM 或内存浪费。
常见错误
- 忘记调用
WithJanitor()——如果不调用,过期条目会一直留在内存中,直到算法将其淘汰。务必在构建器中链式调用.WithJanitor(),并使用defer cache.StopJanitor()。 - 未配置缺失缓存就调用
SetMissing()——会在运行时触发 panic。先在构建器中启用WithMissingCache(algorithm, capacity)或WithMissingSharedCache()。 - 同时使用
WithoutLocking()和WithJanitor()——两者互斥,会触发 panic。WithoutLocking()仅在单个 goroutine 访问且没有后台清理时才安全。 - 缓存过大——缓存如果存下所有数据,就成了一个带有额外开销的 map。请根据工作集设置容量(通常为总数据量的 10%–20%)。监控命中率以验证配置。
- 忽略加载器错误——加载器出错时,
Get()会返回(zero, false, err)。务必检查err,而不只是检查found。
最佳实践
- 始终设置 TTL——无界缓存会无限期提供过期数据,因为没有刷新信号
- 使用
WithJitter(lambda, upperBound)分散过期时间——如果不使用抖动,同时创建的条目会同时过期,导致加载器遭遇惊群效应 - 使用
WithPrometheusMetrics(cacheName)进行监控——命中率低于 80% 通常意味着缓存容量不足,或所选算法不适合当前工作负载 - 对可变值使用
WithCopyOnRead(fn)/WithCopyOnWrite(fn)——如果不复制,调用方会修改缓存对象并破坏共享状态
有关高级模式(重新验证、分片、缺失缓存、监控配置),请参阅生产模式。
有关完整的 API,请参阅 API 参考。
如果在 samber/hot 中遇到错误或意外行为,请前往 https://github.com/samber/hot/issues 提交问题。
交叉引用
- → 有关通用缓存策略,以及何时使用内存缓存、Redis 或 CDN,请参阅
samber/cc-skills-golang@golang-performance技能 - → 有关 Prometheus 指标集成与监控,请参阅
samber/cc-skills-golang@golang-observability技能 - → 有关适用于缓存加载器的数据库查询模式,请参阅
samber/cc-skills-golang@golang-database技能 - → 有关通过 CLI 查询 Prometheus 缓存指标,请参阅
samber/cc-skills@promql-cli技能