使用咖啡因2.8.1和Java8。我已经创建了加载缓存
我已经指定了一个CacheLoader来通过调用
keyExistsOnServer(key)
方法来计算值,该方法调用外部服务来获取值。
我指定了一个自定义过期策略,如果在缓存中创建/更新条目时将该值设置为
如果值为false
,我希望在10分钟内从缓存中逐出该条目。并尽可能长地保存它。最大值真
。
private RemovalListener<String, Boolean> removeListener =
(key, value, cause) ->
logger.info(
"Entry for Key={} with value={} was removed ({}) from cache", key, value, cause);
private LoadingCache<String, Boolean> cache =
Caffeine.newBuilder()
.expireAfter(
new Expiry<String, Boolean>() {
private static final long EXPIRATION_TEN_MINS_IN_NANOSECONDS = 600000000000L;
@Override
public long expireAfterCreate(String key, Boolean value, long currentTime) {
// If value is false that means key does not exist, so set expiration to 10 mins
return value ? Long.MAX_VALUE : EXPIRATION_TEN_MINS_IN_NANOSECONDS;
}
@Override
public long expireAfterUpdate(
String key, Boolean value, long currentTime, long currentDuration) {
// If value is changed from true to false then set expiration to 10 mins
return value ? Long.MAX_VALUE : EXPIRATION_TEN_MINS_IN_NANOSECONDS;
}
@Override
public long expireAfterRead(
String key, Boolean value, long currentTime, long currentDuration) {
// Don't modify expiration time after read
return currentDuration;
}
})
.recordStats()
.removalListener(removeListener)
.build(key -> keyExistsOnServer(key));
问题#1:基于我想要实现的目标,我的过期策略看起来是否正确?
问题#2:
我没有看到按照逐出策略调用RemovalListener
。这可能是由于github问题中所述的清理任务的累积。
然而,我的代码的正确性取决于这样一个事实:一个条目的过期时间(如果false
值为10分钟)已经过去,并且如果我们调用缓存。get(key)
则不应从缓存返回过期值,而是调用CacheLoader
即keyExistsOnServer(key)方法来获取值。有人能断言这就是它的表现吗?
以下是@路易斯·乏色曼在github问题上所说的话,但我不清楚这是否澄清了它:
实际上,get调用本身发现条目已过期,并将其添加到要清理的条目队列中
问题#3:如果CacheLoader
抛出RuntimeException
会发生什么情况,这是调用缓存时的keyExistsOnServer(key)方法。获取(密钥)
?
问题#4:cache.asMap()
是否包含过期但由于权责发生而未被清除的条目?
问题5:当我在expireAfterRead()
方法中记录currentDuration
时,它似乎与经过的时间不一致。i、 e.如果将其设置为60000000000(10分钟),并将值更新为false
我预计5分钟后应为300000000000,但事实并非如此。为什么会这样?
问题#1:基于我想要实现的目标,我的过期策略看起来是否正确?
是的,这看起来不错。您可以将常量设为Duration
,或者使用TimeUnit
进行计算,只是为了让它看起来更漂亮。
问题#2:我看不到拆迁监听者按照拆迁政策被叫来。
当缓存上发生足够多的活动时,就会发生这种情况。您可以指定一个Scheduler
,它将根据下一个条目设置为过期的时间唤醒并为您调用cache.cleanUp
。对于Java9个用户,Java提供了一个内置的调度线程,您可以通过在构建缓存时添加Caffeine.scheduler(Scheduler.systemScheduler)
来利用它。
一旦一个条目的过期时间过去,如果我们调用缓存。get(key),则它不应从缓存返回过期值,而是调用CacheLoader。
正确。缓存将在查找时验证条目,如果过期,则重新加载。它永远不会返回过期的条目。
问题#3:如果CacheLoader抛出运行时异常,该异常是调用缓存时的keyExistsOnServer(key)方法。拿到钥匙了吗?
映射将不会建立,异常将传播到调用方。下一次调用get(key)
将重试,可能再次失败。这是你的选择,如何适应这一点。通常不是这样是一个好答案,或者有时缓存失败是一个更好的答案。
问题#4:cache.asMap()是否包含过期但由于权责发生而未被清除的条目?
缓存将保存条目,但通过查找或迭代等方式抑制它们可见。唯一的外部指示是size()
,因为该计数器在删除过期条目之前不会更新。
问题5:当我在expireAfterRead()方法中记录currentDuration时,它似乎与经过的时间不一致。i、 e.如果将其设置为60000000000(10分钟),并将值更新为false,我预计5分钟后应为300000000000,但事实并非如此。为什么会这样?
请打开单元测试问题,我们可以进行诊断。
我试图使用Spring Boot与咖啡因和一些注释函数。在我们的测试中,对控制器endpoint的异步调用出现了一些问题,这些问题似乎与我们使用非异步缓存的事实有关。 在做一些研究时,我看到了很多使用Caffeine手动使用的例子,但是在和Spring Boot和注释中找不到任何东西。看起来和具有非常不同的API。是否可以异步使用默认的Spring Boot? 谢谢
我计划使用infinispan作为我的Hibernate应用程序二级缓存。My all entities具有生命周期属性[新建- 简单地说,当实体生命周期属性状态到达已完成状态时,我想从缓存中驱逐实体。据我所知,Infinispan不支持自定义驱逐策略。处理我的情况的最佳方式是什么?
我已经使用咖啡因缓存设置了一个场景,但我无法让它工作,当参数相同时,总是调用真正的方法。这是我的配置: 波姆。xml CacheManager的配置类 然后是具有可缓存方法的类: 我还尝试将缓存名称添加到可缓存批注: 并将移动到Spring Boot主应用程序类。 真正的方法总是被调用的。 你知道我做错了什么吗? 谢谢
我目前正在学习咖啡因,总体来说我对Spring还不熟悉。我一直在尝试用咖啡因实现缓存;然而,我发现自己遇到了几个问题。 我看到了两种配置咖啡因缓存的方法。 首先是Java类: 第二是在应用范围内。财产: 我想问一下,这两者之间有什么不同之处吗?我需要课程和应用程序吗。属性配置,还是仅其中一个?此外,在Java类实现中,cacheManager是仅应用于名为“example”的缓存,还是应用于每个缓
我在java Play Framework作业中使用Caffeine cache实现来缓存传出的http请求,我看到,尽管缓存已经启动并运行,但我的服务仍然每次都访问外部服务器,而不是返回缓存中的值。我看到记录在日志中的键总是相同的。 所以我看到没有设置,所以这可能意味着缓存立即过期。但我仍然不知道如何在配置中设置它 我没有更改我的java代码,如果我需要这样做,我找不到任何示例,或者我只应该有一
从Java8开始,我们可以在ConcurrentHashMap上使用。compute*方法来按键同步处理,这样,如果两个线程同时在同一个键上执行。compute*方法,回调仍然会相继执行,而不是同时执行。但是ConcurrentHashMap不能像缓存通常允许的那样提供及时删除数据的能力。 Guava/Caffeine缓存提供了基于时间的自动删除值的能力,但是您没有基于键的同步处理的讨厌特性,如在