golang-samber-hot by samber/cc-skills-golang
npx skills add https://github.com/samber/cc-skills-golang --skill golang-samber-hot角色设定: 你是一位将缓存视为系统设计决策的 Go 工程师。你根据实测的访问模式选择淘汰算法,根据工作集数据确定缓存大小,并且始终为过期、加载器故障和监控做好规划。
这是一个用于 Go 1.22+ 的通用、类型安全的内存缓存库,提供 9 种淘汰算法、TTL、具有单次请求去重的加载器链、分片、过期重验证以及 Prometheus 指标。
官方资源:
本技能介绍并非详尽无遗。更多信息请参阅库的文档和代码示例。Context7 可以作为一个发现平台提供帮助。
go get -u github.com/samber/hot
根据你的访问模式选择算法——错误的算法会浪费内存或导致命中率骤降。
| 算法 | 常量 | 最适合场景 | 应避免场景 |
|---|---|---|---|
| W-TinyLFU | hot.WTinyLFU | 通用、混合工作负载(默认) | 需要简单性以便调试 |
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
| 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 来说过高时才进行切换。
有关详细的算法比较、基准测试和决策树,请参阅算法指南。
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")
加载器通过单次请求去重自动获取缺失的键——针对同一个缺失键的并发 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) // 未命中时触发加载器
在设置缓存容量之前,先估算在内存预算下能容纳多少项:
容量 = 内存预算 / 估算的单条数据大小。向下取整以留出余量。示例:*User 结构体 ~500 字节 + 字符串键 ~50 字节 + 开销 ~100 字节 = ~650 字节/条目
256 MB 预算 → 256_000_000 / 650 ≈ 393,000 项
如果数据项大小未知,请要求开发者通过单元测试来测量,该测试分配 N 个数据项并检查 runtime.ReadMemStats。不进行测量就猜测容量会导致 OOM 或内存浪费。
WithJanitor()——没有它,过期的条目会一直留在内存中,直到算法将其淘汰。始终在构建器中链式调用 .WithJanitor() 并 defer cache.StopJanitor()。SetMissing()——会在运行时引发恐慌。先在构建器中启用 WithMissingCache(algorithm, capacity) 或 WithMissingSharedCache()。WithoutLocking() + WithJanitor()——互斥,会引发恐慌。WithoutLocking() 仅适用于无需后台清理的单协程访问场景。Get() 返回 (零值, false, err)。始终检查 err,而不仅仅是 found。WithJitter(lambda, upperBound) 来分散过期时间——没有抖动,同时创建的项会同时过期,导致加载器上的惊群效应WithPrometheusMetrics(cacheName) 进行监控——命中率低于 80% 通常意味着缓存容量不足或算法不适合当前工作负载WithCopyOnRead(fn) / WithCopyOnWrite(fn)——没有副本,调用者会修改缓存对象并破坏共享状态有关高级模式(重新验证、分片、缺失缓存、监控设置),请参阅生产模式。
完整的 API 接口,请参阅 API 参考。
如果你在 samber/hot 中遇到错误或意外行为,请在 https://github.com/samber/hot/issues 提交 issue。
samber/cc-skills-golang@golang-performance 技能,了解通用缓存策略以及何时使用内存缓存 vs Redis vs CDNsamber/cc-skills-golang@golang-observability 技能,了解 Prometheus 指标集成和监控samber/cc-skills-golang@golang-database 技能,了解与缓存加载器配合使用的数据库查询模式samber/cc-skills@promql-cli 技能,了解通过 CLI 查询 Prometheus 缓存指标每周安装数
99
代码仓库
GitHub 星标数
276
首次出现
4 天前
安全审计
安装于
opencode94
gemini-cli91
codex91
cursor91
kimi-cli90
amp90
Persona: You are a Go engineer who treats caching as a system design decision. You choose eviction algorithms based on measured access patterns, size caches from working-set data, and always plan for expiration, loader failures, and monitoring.
Generic, type-safe in-memory caching library for Go 1.22+ with 9 eviction algorithms, TTL, loader chains with singleflight deduplication, sharding, stale-while-revalidate, and Prometheus metrics.
Official Resources:
This skill is not exhaustive. Please refer to library documentation and code examples for more informations. Context7 can help as a discoverability platform.
go get -u github.com/samber/hot
Pick based on your access pattern — the wrong algorithm wastes memory or tanks hit rate.
| Algorithm | Constant | Best for | Avoid when |
|---|---|---|---|
| W-TinyLFU | hot.WTinyLFU | General-purpose, mixed workloads (default) | You need simplicity for debugging |
| LRU | hot.LRU | Recency-dominated (sessions, recent queries) | Frequency matters (scan pollution evicts hot items) |
| LFU | hot.LFU | Frequency-dominated (popular products, DNS) | Access patterns shift (stale popular items never evict) |
| TinyLFU | hot.TinyLFU | Read-heavy with frequency bias | Write-heavy (admission filter overhead) |
| S3FIFO | hot.S3FIFO | High throughput, scan-resistant | Small caches (<1000 items) |
| ARC | hot.ARC | Self-tuning, unknown patterns | Memory-constrained (2x tracking overhead) |
| TwoQueue | hot.TwoQueue | Mixed with hot/cold split | Tuning complexity is unacceptable |
| SIEVE | hot.SIEVE | Simple scan-resistant LRU alternative | Highly skewed access patterns |
| FIFO | hot.FIFO | Simple, predictable eviction order | Hit rate matters (no frequency/recency awareness) |
Decision shortcut: Start with hot.WTinyLFU. Switch only when profiling shows the miss rate is too high for your SLO.
For detailed algorithm comparison, benchmarks, and a decision tree, see 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")
Loaders fetch missing keys automatically with singleflight deduplication — concurrent Get() calls for the same missing key share one loader invocation:
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
Before setting the cache capacity, estimate how many items fit in the memory budget:
capacity = memoryBudget / estimatedItemSize. Round down to leave headroom.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
If the item size is unknown, ask the developer to measure it with a unit test that allocates N items and checks runtime.ReadMemStats. Guessing capacity without measuring leads to OOM or wasted memory.
WithJanitor() — without it, expired entries stay in memory until the algorithm evicts them. Always chain .WithJanitor() in the builder and defer cache.StopJanitor().SetMissing() without missing cache config — panics at runtime. Enable WithMissingCache(algorithm, capacity) or WithMissingSharedCache() in the builder first.WithoutLocking() + WithJanitor() — mutually exclusive, panics. WithoutLocking() is only safe for single-goroutine access without background cleanup.WithJitter(lambda, upperBound) to spread expirations — without jitter, items created together expire together, causing thundering herd on the loaderWithPrometheusMetrics(cacheName) — hit rate below 80% usually means the cache is undersized or the algorithm is wrong for the workloadWithCopyOnRead(fn) / WithCopyOnWrite(fn) for mutable values — without copies, callers mutate cached objects and corrupt shared stateFor advanced patterns (revalidation, sharding, missing cache, monitoring setup), see Production Patterns.
For the complete API surface, see API Reference.
If you encounter a bug or unexpected behavior in samber/hot, open an issue at https://github.com/samber/hot/issues.
samber/cc-skills-golang@golang-performance skill for general caching strategy and when to use in-memory cache vs Redis vs CDNsamber/cc-skills-golang@golang-observability skill for Prometheus metrics integration and monitoringsamber/cc-skills-golang@golang-database skill for database query patterns that pair with cache loaderssamber/cc-skills@promql-cli skill for querying Prometheus cache metrics via CLIWeekly Installs
99
Repository
GitHub Stars
276
First Seen
4 days ago
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode94
gemini-cli91
codex91
cursor91
kimi-cli90
amp90
GSAP 框架集成指南:Vue、Svelte 等框架中 GSAP 动画最佳实践
3,200 周安装
Get() returns (zero, false, err) on loader failure. Always check err, not just found.