为什么我在使用 Spring 缓存的服务中有缓存未命中
Why I have cache misses in Service using Spring Cache
我的缓存配置如下:
@Configuration
@EnableCaching
public class CacheConfig {
@Bean(name = "caffeineCachingProvider")
public CachingProvider caffeineCachingProvider() {
return Caching.getCachingProvider("com.github.benmanes.caffeine.jcache.spi.CaffeineCachingProvider");
}
@Bean(name = "caffeineCacheManager")
public JCacheCacheManager getSpringCacheManager() {
CacheManager cacheManager = caffeineCachingProvider().getCacheManager();
CaffeineConfiguration<String, List<Product>> caffeineConfiguration = new CaffeineConfiguration<>();
caffeineConfiguration.setExpiryPolicyFactory(FactoryBuilder.factoryOf(new AccessedExpiryPolicy(new Duration(TimeUnit.MINUTES, 60))));
caffeineConfiguration.setCopierFactory(Copier::identity);
cacheManager.createCache("informerCache", caffeineConfiguration);
return new JCacheCacheManager(cacheManager);
}
}
我还有 @Service
以下列方式使用它:
@Service
public class InformerService {
@CacheResult(cacheName = "informerCache")
public List<Product> getProducts(@CacheKey String category, @CacheKey String countrySign, @CacheKey long townId) throws Exception {
Thread.sleep(5000);
// do some work
}
}
所以我有下一个行为。
- 当我第一次调用服务方法时需要 5 秒
然后按预期做一些工作。
- 第二次使用相同的参数调用方法 -> 缓存工作 -> returns 立即得到结果
- 第三次使用相同的参数再次调用导致
Thread.sleep
从头再来。
如何解决这个问题?那是关于代理的问题吗?我错过了什么?
如评论中所述,这是 JCache 适配器中的错误。谢谢你让我知道这个问题。我发布了版本 2.1.0 which includes this fix. That release also includes friendlier initial settings for CaffeineConfiguration
which you identified in another .
虽然核心库经过了大量测试,但 JCache 适配器过于依赖 JSR 的 TCK(测试兼容性工具包)。不幸的是,该测试套件不是很有效,所以我添加了测试以帮助避免将来出现此类错误。
此问题只发生在JCache 中,因为Caffeine 的核心库不支持其过期版本。 Caffeine 更喜欢使用 O(1) 设计,通过使用固定持续时间来急切清理过期条目。 JCache 使用 per-entry 惰性过期并且规范作者假设使用容量约束来最终丢弃过期的条目。我在有关此功能的文档中添加了 warning,因为它可能容易出错。虽然 none 的其他 JCache 实现超出了这一范围,但一项悬而未决的任务是确定一种机制来帮助缓解此 JCache 设计缺陷。
再次感谢您报告此问题。一如既往,如果您有任何其他问题或反馈要分享,请随时与我们联系。
我的缓存配置如下:
@Configuration
@EnableCaching
public class CacheConfig {
@Bean(name = "caffeineCachingProvider")
public CachingProvider caffeineCachingProvider() {
return Caching.getCachingProvider("com.github.benmanes.caffeine.jcache.spi.CaffeineCachingProvider");
}
@Bean(name = "caffeineCacheManager")
public JCacheCacheManager getSpringCacheManager() {
CacheManager cacheManager = caffeineCachingProvider().getCacheManager();
CaffeineConfiguration<String, List<Product>> caffeineConfiguration = new CaffeineConfiguration<>();
caffeineConfiguration.setExpiryPolicyFactory(FactoryBuilder.factoryOf(new AccessedExpiryPolicy(new Duration(TimeUnit.MINUTES, 60))));
caffeineConfiguration.setCopierFactory(Copier::identity);
cacheManager.createCache("informerCache", caffeineConfiguration);
return new JCacheCacheManager(cacheManager);
}
}
我还有 @Service
以下列方式使用它:
@Service
public class InformerService {
@CacheResult(cacheName = "informerCache")
public List<Product> getProducts(@CacheKey String category, @CacheKey String countrySign, @CacheKey long townId) throws Exception {
Thread.sleep(5000);
// do some work
}
}
所以我有下一个行为。
- 当我第一次调用服务方法时需要 5 秒 然后按预期做一些工作。
- 第二次使用相同的参数调用方法 -> 缓存工作 -> returns 立即得到结果
- 第三次使用相同的参数再次调用导致
Thread.sleep
从头再来。
如何解决这个问题?那是关于代理的问题吗?我错过了什么?
如评论中所述,这是 JCache 适配器中的错误。谢谢你让我知道这个问题。我发布了版本 2.1.0 which includes this fix. That release also includes friendlier initial settings for CaffeineConfiguration
which you identified in another
虽然核心库经过了大量测试,但 JCache 适配器过于依赖 JSR 的 TCK(测试兼容性工具包)。不幸的是,该测试套件不是很有效,所以我添加了测试以帮助避免将来出现此类错误。
此问题只发生在JCache 中,因为Caffeine 的核心库不支持其过期版本。 Caffeine 更喜欢使用 O(1) 设计,通过使用固定持续时间来急切清理过期条目。 JCache 使用 per-entry 惰性过期并且规范作者假设使用容量约束来最终丢弃过期的条目。我在有关此功能的文档中添加了 warning,因为它可能容易出错。虽然 none 的其他 JCache 实现超出了这一范围,但一项悬而未决的任务是确定一种机制来帮助缓解此 JCache 设计缺陷。
再次感谢您报告此问题。一如既往,如果您有任何其他问题或反馈要分享,请随时与我们联系。