Caffeine Cache中expireAfterWrite参数工作机制及过期条目删除问题问询
Caffeine Cache: expireAfterWrite 过期清理机制与优化方案
过期条目的删除触发逻辑
Caffeine的过期清理采用惰性清理+后台异步清理的组合模式:
getIfPresent()会触发清理:查询时先检查目标条目是否过期,若已过期则直接删除并返回null;同时会随机抽样少量其他条目(默认每次读操作抽3个),清理其中的过期条目。size()不会触发清理:默认size()返回的是缓存的逻辑计数,包含已过期但尚未被清理的条目,调用该方法不会主动触发删除操作。
高写入、低查询场景的解决办法
如果缓存只有大量写入却很少有读请求,惰性清理的触发机会不足,容易导致过期条目堆积。无需定时调用size(),可采用以下方案:
1. 配置后台异步清理调度器
这是最推荐的方式,Caffeine支持通过内置调度器定期异步扫描并清理过期条目,完全不依赖读写操作。示例代码:
Cache<String, Object> cache = Caffeine.newBuilder() .expireAfterWrite(10, TimeUnit.MINUTES) .scheduler(Scheduler.systemScheduler()) // 采用系统默认调度器,默认1分钟扫描一次 .build();
你也可以通过自定义Scheduler调整扫描频率,或使用Scheduler.forExecutor()传入自定义线程池来控制资源占用。
2. 结合容量限制驱逐
如果内存占用是核心顾虑,可搭配maximumSize()或maximumWeight()配置。当缓存达到容量上限时,Caffeine会自动触发驱逐逻辑,优先清理过期条目,再按LRU等策略驱逐未过期条目,避免内存溢出:
Cache<String, Object> cache = Caffeine.newBuilder() .expireAfterWrite(10, TimeUnit.MINUTES) .maximumSize(10000) // 限制最大有效条目数 .build();
3. 写入时触发轻量清理(谨慎使用)
若有特殊需求,可在每次写入后调用cleanUp()同步清理,但该操作会阻塞当前线程,可能影响写入性能,仅在必要时使用:
cache.put(key, value); cache.cleanUp(); // 同步清理所有可立即删除的过期条目
内容的提问来源于stack exchange,提问作者Alex Tbk
相关产品推荐
相关产品推荐

