TL;DR

  • 场景: 在 Java 项目中使用 Guava Cache 做本地缓存,需要理清删除策略、过期机制与常见坑
  • 结论: Guava Cache 采用”懒清理 + LRU+FIFO”策略,被动删除和主动删除需要配合使用
  • 产出: 删除策略全解 + 过期机制详解 + 错误速查卡

Guava Cache 数据删除机制

1. 被动删除

基于大小的删除: 当缓存元素数量达到预设最大容量时,按LRU(最近最少使用)算法自动移除最久未使用的条目。

基于时间的删除:

  • expireAfterAccess: 条目在指定时间内未被访问自动移除
  • expireAfterWrite: 条目在创建或更新后超过指定时间自动移除

基于引用的删除: 使用弱引用(WeakReference)或软引用(SoftReference)包装值时,内存不足会被垃圾回收器自动回收。

2. 主动删除

  • 显式调用 invalidate 方法删除单个键
  • 调用 invalidateAll 方法批量删除
  • 通过 RemovalListener 监听删除事件
  • 调用 cleanUp 方法主动清理过期条目

重要说明:懒删除机制

Guava Cache 采用惰性删除机制。“超过过期时间后,cache.size() 仍未下降”是因为未触发访问/维护逻辑,或未调用 cleanUp

解决方案:

  • 在定时任务或关键路径补充 cache.cleanUp()
  • 或通过访问触发回收

错误速查表

症状根因定位修复
过期时间后 size 未下降惰性删除未触发调用 cleanUp() 或触发访问
maximumSize 达上限但未淘汰LRU+FIFO 策略与预期不一致打印 cache.asMap() 调试
内存占用持续升高未限制 maximumSize 或过期策略设置合理参数

应用场景示例

  • 电商平台商品缓存: 使用 expireAfterWrite 确保价格信息定期更新
  • 用户会话管理: 使用 expireAfterAccess 自动清理长时间不活跃的用户会话
  • 热点数据缓存: 使用基于大小的删除防止缓存占用过多内存