【问题标题】:Guava CacheBuilder doesn't call removalListener immediately after cache expiryGuava CacheBuilder 在缓存到期后不会立即调用removingListener
【发布时间】:2019-06-18 17:52:55
【问题描述】:

从我的应用程序日志中,我觉得在缓存键过期后不会立即调用 removeListener。这在以下场景中产生了问题

缓存配置:

SimpleCacheManager simpleCacheManager = new SimpleCacheManager();
GuavaCache cache = new GuavaCache("cacheData", CacheBuilder.newBuilder().expireAfterAccess(10, TimeUnit.MINUTES).removalListener(expiredCacheListener()).build());

在应用程序逻辑中,我看到当调用cache.get(key) 时,如果没有值(因为缓存因expireAfterAccess() 方法时间限制而过期),那么它会在缓存中放置一个新值由于旧密钥已过期/已删除,因此密钥相同。

在这个写操作之后,我认为removingListener正在调用expiredCacheListener()方法,该方法具有更改过期键值的逻辑.... //但这实际上是在更改新值! !

现在我在缓存中有一个值不正确的有效键

如果一个线程能够使一个键过期,那么同一个线程不应该立即调用removingListener吗?我该如何解决这个问题?

【问题讨论】:

  • 如果需要,您可以使用https://codeshare.io/ 实时共享代码

标签: java caching guava


【解决方案1】:

这就是 Guava Cache 的工作原理,参见CachesExplained

什么时候进行清理?

使用CacheBuilder 构建的缓存不执行清理和驱逐值 “自动”或在值过期后立即,或任何 排序。相反,它在期间执行少量维护 写操作,或者在偶尔的读操作期间,如果写是 很少见。

阅读更多内容以了解 Guava 创作者“将选择权交给您”;您可以自行维护清理线程。

对于更高级的Cache 用例,请使用Caffeine,它“使用受 Google Guava 启发的 API 提供内存缓存”。 Removal wiki 页面提到,对于同步删除侦听器,您可以使用 CacheWriter

【讨论】:

  • 我是否可以以某种方式手动进行检查以验证 expired 键是否在我的 expiredCacheListener() 方法中被新值覆盖?在调用removeListner() 时,缓存键具有新值,因此不应将 removeListener() 逻辑应用于该键,因为它不应再被视为过期键
  • 是否可以获得缓存中存在的过期密钥列表(在我手动执行cleanUp()之前我想检查一下)?
  • @firstpostcommenter "当 removeListner() 被调用时,缓存键有一个新值,因此 removeListener() 逻辑不应该应用于键,因为它不应该被视为已过期的密钥”这不是缓存的工作方式。移除监听器只会在实际移除的旧值上被调用;它不会在新计算的值上调用。您无需在这里做任何特别的事情。
猜你喜欢
  • 1970-01-01
  • 2014-03-26
  • 2011-11-08
  • 2016-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-26
相关资源
最近更新 更多