tinylfu准入策略本质是轻量级频率筛检机制:仅用12位计数器+count-min sketch估算key访问趋势,预估低价值即拒绝写入,不占内存、不触发淘汰;numcounters需设为10×maxcost量级以防哈希冲突误拒高频key。

TinyLFU 准入策略不是“放行所有热数据”,而是用极小代价(12位计数器)筛掉大概率低价值的写入
很多开发者以为 TinyLFU 是个“智能判断是否该缓存”的黑盒,实际它只做一件事:在 Set() 时快速估算这个 key 的访问频率趋势,若预估长期价值偏低,就直接拒绝写入——不进缓存、不占内存、不触发淘汰逻辑。这和传统“先写再淘汰”有本质区别。
关键点:
-
TinyLFU依赖NumCounters参数(默认1e7),值太小会导致哈希冲突激增,把高频 key 当作噪声拒掉;建议设为10 * MaxCost量级 - 它不维护完整访问历史,只靠 Count-Min Sketch 统计采样频次,所以对突发流量(如秒杀首波请求)识别滞后,前几次可能被误拒
- 没有 TTL 或权重参与准入决策——
cost和ttl只影响后续淘汰,不影响TinyLFU是否放行 - 如果你发现大量
Set()后Get()不命中,且cache.Metrics().Gets远高于cache.Metrics().Hits,大概率是NumCounters设置过小或工作负载 Zipf 分布太陡
SampledLFU 淘汰机制怎么选中要删的 key
SampledLFU 不遍历全量缓存,而是在每次淘汰时随机采样一批 storeItem(默认 16 个),从中挑出“频率计数最低 + 成本最高”的组合项驱逐。这意味着:
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 它不保证精确 LRU 行为,但实测在搜索/数据库类负载下命中率反超 LRU —— 因为真实场景中“最近访问”不等于“未来还会访问”
- 淘汰决策受
cost显著影响:一个cost=100的大对象,可能换掉 10 个cost=1的小对象,这是IgnoreInternalCost: false时的核心逻辑 - 如果关闭成本感知(
IgnoreInternalCost: true),则退化为纯频次驱动,此时MaxCost就变成纯条目数限制,和示例里MaxCost: 10那种用法一致 - 采样本身有随机性,所以同一缓存实例在相同压力下,两次淘汰的 key 可能不同——别依赖淘汰顺序做业务假设
为什么 ristretto.NewCache() 后必须调用 Wait()
ristretto 把写入拆成两阶段:Set() 只写入无锁 buffer,异步批量刷到分片 map;Wait() 等待 buffer 刷完。不调用 Wait() 就读不到刚写的值,尤其在测试或短生命周期服务中极易踩坑。
- 生产环境通常不需要显式
Wait(),因为请求链路自然延展了时间窗口 - 单元测试里漏掉
Wait(),会看到Get()返回nil, false,但Set()没报错——这不是 bug,是设计使然 -
Wait()是阻塞调用,高并发写入时慎用;更稳妥的方式是用time.Sleep(1ms)或依赖后续真实读请求触发 flush - buffer 大小由
BufferItems控制(默认 64),调得太小会导致频繁 flush,增大锁争用;太大则延迟上升
sync.Map 和 ristretto 在高并发写场景下的真实差异
别被“并发安全”字面意思骗了。sync.Map 读快写慢,写操作需锁整个 dirty map;ristretto 的分片 map(256 个 lockedMap)让写竞争概率下降两个数量级。
- 压测显示:16 核机器上,10k goroutine 并发
Set(),sync.Map吞吐跌到 2w ops/s 以下,ristretto仍稳定在 80w+ ops/s -
ristretto的写吞吐几乎不随 goroutine 数线性衰减,而sync.Map在 goroutine 超过 CPU 核数 2 倍后就开始明显抖动 - 但
ristretto内存占用固定(由MaxCost和NumCounters决定),sync.Map会无限增长——这点常被忽略 - 如果只是存配置、开关等极少更新的数据,
sync.Map更轻量;一旦涉及高频写+有限内存+高命中率诉求,ristretto的准入/淘汰协同才是关键
真正难调的是 NumCounters 和 MaxCost 的配比——它不像内存配额那样直观,得结合实际 trace 数据看 Metrics().Admissions 和 Metrics().Evictions 的比率,反复压测才能稳住。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










