寻求支持自定义驱逐触发策略或可查询下一个可驱逐key的Java缓存库
解决方案
下面给出3种可直接落地的实现方案,无需自行实现完整缓存淘汰算法:
方案1:使用Caffeine缓存库(优先推荐)
Caffeine是Guava Cache的官方继任实现,性能优于Guava Cache,原生提供公开API直接支持待淘汰键的查询:
- 配置缓存时不设置
maximumSize/maximumWeight参数,或设置为远大于元数据体量的阈值,关闭自动驱逐逻辑 - 每次需要获取下一个可驱逐键时,直接调用缓存实例的
policy().eviction()接口,调用nextEvictable()方法即可拿到待淘汰的键 - 在你的磁盘容量监控逻辑触发阈值时,主动调用
cache.invalidate(key)淘汰对应缓存条目,同时执行磁盘文件清理逻辑即可
方案2:反射调用Guava Cache内部方法
如果当前项目已依赖Guava且不便更换缓存框架的场景可使用该方案:
- 拿到Guava Cache实例后,反射获取其底层的
LocalCache实例 - 反射获取
getNextEvictable()方法,设置setAccessible(true)解除访问权限限制 - 需要获取待淘汰键时调用该方法即可
- 注意:Guava版本迭代时可能变更内部方法名或结构,建议固定Guava版本或增加版本兼容校验逻辑
方案3:基于JDK原生LinkedHashMap实现轻量封装
如果不想引入额外第三方缓存依赖可使用该方案,LinkedHashMap原生支持LRU淘汰顺序:
- 初始化
LinkedHashMap时设置accessOrder = true开启LRU访问顺序 - 重写
removeEldestEntry方法,固定返回false,关闭自动淘汰逻辑 - 用
Collections.synchronizedMap包装得到线程安全的Map实例 - 需要获取下一个可驱逐键时,调用
firstEntry()方法即可拿到最久未访问的待淘汰条目,主动移除即可
注意:该方案仅支持LRU淘汰策略,若需要LFU等其他淘汰策略不适用。
内容的提问来源于stack exchange,提问作者LearningToCode
相关产品推荐
相关产品推荐

