在 Golang 中使用 samber/hot 进行内存缓存,支持 LRU、LFU、TinyLFU、W‑TinyLFU、S3FIFO、ARC、TwoQueue、SIEVE、FIFO 等淘汰算法,提供 TTL、缓存加载器及分片功能。
Persona: 您是一位将缓存作为系统设计决定的Go工程师是一项面向实际任务的技能,主要用于您选择基于测量访问模式的驱逐算法, 从工作集数据中选择大小缓存, 并且总是。它将相关步骤、工具调用和结果整理方式集中到统一流程中,帮助使用者更快完成目标并减少重复操作。
实际使用前应先确认任务范围、数据来源、运行环境、必要权限和关键参数,再依据技能说明逐步执行;若输入条件不完整,应先补齐信息或采用保守配置,避免因错误假设导致结果偏离需求。
执行过程中需要关注工具调用是否成功、接口或依赖是否可用、输出格式是否符合预期,并对异常提示、缺失字段和边界情况进行处理;涉及批量任务时,还应保存进度,避免中断后重复操作。
角色定位:你是一名 Go 工程师,将缓存视为一项系统设计决策。你会基于实测的访问模式选择逐出算法,依据工作集数据确定缓存容量,并始终为过期、加载器失败及监控做好规划。
一款面向 Go 1.22+ 的泛型、类型安全的内存缓存库,支持 9 种逐出算法、TTL、带 singleflight 去重能力的加载器链、分片(sharding)、stale-while-revalidate 语义,以及 Prometheus 指标导出功能。
官方资源:
本技能内容并非详尽无遗。更多细节请参考该库的文档与代码示例。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 |
自适应调优、访问模式未知 | 内存受限(需两倍跟踪开销) |
| TwoQueue | hot.TwoQueue |
混合型负载,且可清晰区分热/冷数据 | 无法接受调优复杂度 |
| SIEVE | hot.SIEVE |
轻量级、抗扫描的 LRU 替代方案 | 访问模式高度倾斜(如极少数 key 占据绝大部分访问) |
| FIFO | hot.FIFO |
结构简单、逐出顺序可预测 | 命中率至关重要(完全不感知访问频率与时效性) |
快速决策建议:默认从 hot.WTinyLFU 开始;仅当性能剖析显示未命中率超出服务等级目标(SLO)时,再考虑切换算法。
如需详细算法对比、基准测试结果与决策树,请参阅《Algorithm Guide》。
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")
加载器会在 key 缺失时自动拉取数据,并通过 singleflight 实现并发去重——对同一缺失 key 的多次 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) // 批量查询
}).
WithJanitor().
Build()
defer cache.StopJanitor()
user, found, err := cache.Get(123) // 缺失时自动触发加载器
设定缓存容量前,请先估算内存预算内可容纳多少条目:
capacity = memoryBudget / estimatedItemSize,向下取整以预留余量。示例:*User 结构体约 500 字节 + string 类型 key 约 50 字节 + 内部开销约 100 字节 = 每条目约 650 字节
256 MB 预算 → 256_000_000 / 650 ≈ 393,000 条目
若单条目大小未知,请让开发人员编写单元测试:批量创建 N 个实例并调用 runtime.ReadMemStats 进行实测。未经测量而盲目估算容量,极易导致 OOM 或内存浪费。
WithJanitor():若未启用清理器(janitor),过期条目将持续驻留内存,直至被逐出算法淘汰。务必在构建器中链式调用 .WithJanitor(),并在退出前 defer cache.StopJanitor()。SetMissing():运行时 panic。请先在构建器中启用 WithMissingCache(algorithm, capacity) 或 WithMissingSharedCache()。WithoutLocking() 和 WithJanitor():二者互斥,将 panic。WithoutLocking() 仅适用于单 goroutine 访问且无需后台清理的场景。Get() 返回 (zero, false, err)。务必检查 err,不可仅依赖 found 判断。WithJitter(lambda, upperBound) 分散过期时间 —— 若无 jitter,同批创建的条目将集中过期,引发加载器端的“惊群效应”(thundering herd)WithPrometheusMetrics(cacheName) 启用监控 —— 命中率低于 80% 通常表明缓存容量不足或算法不匹配当前负载WithCopyOnRead(fn) / WithCopyOnWrite(fn) —— 若不复制,调用方直接修改缓存对象将破坏共享状态如需了解高级模式(再验证、分片、缺失缓存、监控集成等),请参阅《Production Patterns》。
如需完整 API 接口说明,请查阅《API Reference》。
若在使用 samber/hot 过程中遇到 bug 或非预期行为,请前往 https://github.com/samber/hot/issues 提交 issue。
samber/cc-skills-golang@golang-performance 技能,了解通用缓存策略,以及何时选用内存缓存、Redis 或 CDNsamber/cc-skills-golang@golang-observability 技能,了解 Prometheus 指标集成与监控方法samber/cc-skills-golang@golang-database 技能,了解适配缓存加载器的数据库查询模式samber/cc-skills@promql-cli 技能,学习如何通过 CLI 查询 Prometheus 缓存指标相关专题
热门下载
相关下载
精品课程
共0课时 | 0人学习
共0课时 | 0人学习
共0课时 | 0人学习