mcpField
G
golang-samber-hot

golang-samber-hot

github.com/samber开发3.7k38.6k 次安装5 天前更新
代码仓库

关于 golang-samber-hot

面向 Go 工程师的 samber/hot 缓存使用技能,介绍 Go 1.22+ 的泛型内存缓存及其配置。内容涵盖淘汰策略、过期、加载器、分片和指标监控。

主要功能

  1. 019 种缓存淘汰算法
  2. 02TTL 与过期清理
  3. 03带 singleflight 去重的加载器
  4. 04分片与过期时重新验证
  5. 05Prometheus 指标

适用场景

  1. 01按访问模式选择淘汰算法
  2. 02缓存数据库读取并合并并发加载
  3. 03通过 TTL 与抖动管理过期
  4. 04监控缓存命中率并调整容量

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/samber/cc-skills-golang --skill golang-samber-hot

安装后在 Claude Code 中输入/golang-samber-hot确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

evals/
evals.json
references/
algorithm-guide.md
api-reference.md
production-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-TinyLFUhot.WTinyLFU通用、混合工作负载(默认)需要便于调试的简单算法
LRUhot.LRU由近期访问主导(会话、近期查询)频率很重要(扫描污染会淘汰热点条目)
LFUhot.LFU由访问频率主导(热门产品、DNS)访问模式会变化(过时的热门条目始终无法淘汰)
TinyLFUhot.TinyLFU读取密集且偏重访问频率写入密集(准入过滤器开销较大)
S3FIFOhot.S3FIFO高吞吐量、抗扫描小型缓存(<1000 个条目)
ARChot.ARC自动调优、模式未知内存受限(跟踪开销为 2 倍)
TwoQueuehot.TwoQueue热/冷分区的混合工作负载无法接受调优的复杂性
SIEVEhot.SIEVE简单且抗扫描的 LRU 替代方案访问模式高度倾斜
FIFOhot.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

容量规划

设置缓存容量前,请估算内存预算可以容纳多少条目:

  1. 估算单条目大小——估算结构体的大小,并加上堆上分配的字段(切片、映射、字符串)的大小。还要计入键的大小。每个条目的内部管理开销约为 100 字节,可粗略覆盖内部簿记所需空间(指针、过期时间戳、算法元数据)。
  2. 询问开发者生产环境中为此缓存分配了多少内存(例如,256 MB、1 GB)。这取决于服务的总内存以及进程中其他共享资源的情况。
  3. 计算容量——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 或内存浪费。

常见错误

  1. 忘记调用 WithJanitor()——如果不调用,过期条目会一直留在内存中,直到算法将其淘汰。务必在构建器中链式调用 .WithJanitor(),并使用 defer cache.StopJanitor()。
  2. 未配置缺失缓存就调用 SetMissing()——会在运行时触发 panic。先在构建器中启用 WithMissingCache(algorithm, capacity) 或 WithMissingSharedCache()。
  3. 同时使用 WithoutLocking() 和 WithJanitor()——两者互斥,会触发 panic。WithoutLocking() 仅在单个 goroutine 访问且没有后台清理时才安全。
  4. 缓存过大——缓存如果存下所有数据,就成了一个带有额外开销的 map。请根据工作集设置容量(通常为总数据量的 10%–20%)。监控命中率以验证配置。
  5. 忽略加载器错误——加载器出错时,Get() 会返回 (zero, false, err)。务必检查 err,而不只是检查 found。

最佳实践

  1. 始终设置 TTL——无界缓存会无限期提供过期数据,因为没有刷新信号
  2. 使用 WithJitter(lambda, upperBound) 分散过期时间——如果不使用抖动,同时创建的条目会同时过期,导致加载器遭遇惊群效应
  3. 使用 WithPrometheusMetrics(cacheName) 进行监控——命中率低于 80% 通常意味着缓存容量不足,或所选算法不适合当前工作负载
  4. 对可变值使用 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 技能

评论

支持 Markdown