ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Caffeine驱逐策略详解:maximumSize与Weigher如何精准释放缓存空间

Caffeine驱逐策略详解:maximumSize与Weigher如何精准释放缓存空间 Caffeine驱逐策略详解maximumSize与Weigher如何精准释放缓存空间【免费下载链接】caffeineA high performance caching library for Java项目地址: https://gitcode.com/gh_mirrors/ca/caffeineCaffeine 是 Java 生态中公认的高性能内存缓存库其核心卖点之一就是基于频率与新鲜度TinyLFU的智能驱逐策略。本文面向新手和普通用户完整讲解 Caffeine 驱逐策略两大基石——maximumSize与Weigher它们如何共同决定缓存装满了怎么办、先踢掉谁让你的缓存精准释放空间、把命中率保持在接近理论最优的水平。一、为什么需要驱逐—— 缓存空间的预算问题缓存的本质是一块有限的内存。当数据不断写入总有一天会装满此时必须有人被请出去这就是驱逐Eviction。Caffeine 把这件事拆成两个独立的问题问题对应配置解决的问题缓存最多能装多少maximumSize/maximumWeight设定容量预算超预算时踢掉谁TinyLFU 策略自动选择最不值得留的条目前者由你在构建缓存时声明后者由 Caffeine 自动完成。两个问题分开理解驱逐策略就不难了。二、maximumSize最简单的按条数限制最直接的容量控制是限制条目数量即maximumSize。例如限制缓存最多保留 10,000 个条目超出的部分就会被策略自动驱逐。它定义在 Caffeine.java 中。使用上有几个新手必须知道的细节阈值不是硬墙官方文档明确说明缓存可能在达到上限之前就开始驱逐驱逐过程中也可能短暂超出阈值——这是为了摊平驱逐开销、避免集中大扫除式的卡顿。设为 0 等于禁用缓存条目加载后立即被驱逐非常适合在测试环境或线上临时关掉缓存而无需改代码。不能与maximumWeight同时使用二者是同一容量预算的两种度量单位二选一即可。适合maximumSize的场景每个缓存条目大小相对均匀比如用户名 → 用户信息、ID → 订单对象。三、Weigher maximumWeight按重量精确控容量现实中缓存条目的大小往往差异巨大一条 5KB 的摘要和一张 2MB 的缩略图图数据用条数来算账显然不公平。这时就需要给每个条目称一重量。Caffeine 提供了Weigher函数式接口见 Weigher.java你只需实现weigh(key, value)方法返回该条目的重量。重量没有单位只表示条目之间的相对大小常见做法是返回序列化的字节数、列表元素个数或内存估算值。配置上遵循一条铁律maximumWeight与weigher必须成对出现——只配其一会被忽略或报错参见 Caffeine.java 中的校验逻辑。几个关键行为来自 Caffeine.java 的文档说明总重量一旦超过maximumWeight驱逐就会启动直到降回预算之内单个条目的重量只会超过总预算时它会被立即驱逐无论它有多热门重量为 0 的条目不参与基于大小的驱逐但仍可能被时间过期等其他方式移除一个反直觉的要点重量只用于判断是否超容量并不影响选谁被驱逐——谁被踢走仍然完全由 TinyLFU 策略决定。一句话记忆maximumWeight 管账本上限Weigher 管每笔账的大小TinyLFU 管先销哪笔账。四、谁被驱逐TinyLFU 智能准入过滤器Caffeine 之所以高效靠的是对经典的 TinyLFU 策略的实现。缓存内部被划分为三个区域整体架构如下图所示图Caffeine 驱逐策略架构——新条目先进入准入窗口Window再与试用区Probation/保护区Protected按频率竞争去留工作流程可以概括为四步新条目先住试住间刚加载的条目进入准入窗口而不是直接获得长期居留权试用区候补窗口空间满后条目被晋升到试用区Probation按最近使用顺序排队频率对决当缓存超过容量预算候补者与受害者队列尾端条目各报一次访问频率频率低的一方被驱逐——这正是 BoundedLocalCache.java 中evictFromMain的核心逻辑热门晋升在试用区反复命中的条目会晋升到保护区受到更好的保护。频率统计由 FrequencySketch.java 提供的计数草图完成用极小的内存开销就能近似记录每个条目的访问热度这也是 Caffeine 在多种真实负载上接近理论最优命中率的关键。不同负载下的效率表现可参考下图图Caffeine 驱逐策略在典型 OLTP 负载下的缓存效率表现对驱逐结果感兴趣的话还可以开启统计并观察命中曲线图Caffeine 模拟器Simulator在不同缓存策略下的命中速率对比五、如何观察驱逐行为—— Policy 驱逐监控 API驱逐发生时Caffeine 会记录移除原因RemovalCause定义在 RemovalCause.java 中常见取值包括SIZE因超过maximumSize/maximumWeight被驱逐本文主角EXPIRED/COLLECTED分别因时间过期、弱引用被 GC 回收而移除REPLACED/EXPLICIT被更新替换或被显式invalidate。通过removalListener你可以打印每个被驱逐条目的原因验证自己的容量配置是否合理。此外Policy.java 提供的eviction()接口还能查看试用区/保护区条目的实时分布是调优时的透视镜。六、新手常见误区与最佳实践误区一把 maximumSize 当成精确上限。它更像高水位允许少量提前/滞后驱逐别用断言去卡死缓存大小。误区二Weigher 返回精确字节数。重量只是相对值返回序列化字节数 / 某固定单位即可越轻量越好——它会在每次插入、更新时被调用。误区三只用 maximumSize 忽略大小差异。如果你的 value 是图片、大文本、变长列表务必改用maximumWeight weigher否则一条大记录可能吃光整块内存预算。误区四容量设置过小。驱逐越频繁回源压力越大。建议先用 README 中提到的Simulator扩展用真实流量回放估算合适的容量与命中率再上线微调。✅实践建议清单场景推荐配置条目大小均匀如用户信息maximumSize(n)即可条目大小悬殊图片、列表maximumWeight(bytes)weigher需要临时停用缓存设maximumSize(0)或maximumWeight(0)想验证策略效果开启统计 removalListener观察SIZE原因占比七、总结maximumSize按条目数限容最简单通用maximumWeight Weigher按重量限容适合大小悬殊的值两者互斥、二选一。无论哪种限容方式驱逐谁都由 TinyLFU 策略自动裁决新条目先过准入窗口再按访问频率与受害者对决频率低者出局。驱逐只负责释放空间命中率的成败取决于容量预算是否贴近工作集大小——善用模拟器与Policy监控 API让每一次驱逐都精准释放在最该释放的空间上。【免费下载链接】caffeineA high performance caching library for Java项目地址: https://gitcode.com/gh_mirrors/ca/caffeine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表