2

我的缓存配置如下:

@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
    }
}

所以我有下一个行为。

  1. 当我第一次调用服务方法时,它需要 5 秒,然后按预期完成一些工作。
  2. 第二次使用相同的参数调用方法->缓存有效->立即返回结果
  3. 再次使用相同的参数调用第三次会导致Thread.sleep

一切从头再来。

如何解决这个问题?这是关于代理的问题吗?我错过了什么 ?

4

1 回答 1

3

正如评论中所讨论的,这是 JCache 适配器中的一个错误。感谢您让我知道这个问题。我发布了包含此修复程序的2.1.0版。CaffeineConfiguration该版本还包括您在另一篇文章中确定的友好的初始设置。

虽然核心库经过大量测试,但 JCache 适配器过于依赖 JSR 的 TCK(测试兼容性工具包)。不幸的是,该测试套件不是很有效,所以我添加了测试来帮助避免将来出现这些类型的错误。

这个问题只出现在 JCache 中,因为 Caffeine 的核心库不支持它的过期版本。Caffeine 更喜欢使用 O(1) 设计,该设计通过使用固定持续时间来急切地清理过期条目。JCache 使用每个条目的延迟过期,并且规范作者假设使用容量约束来最终丢弃过期的条目。我在文档中添加了有关此功能的警告,因为它可能容易出错。尽管其他的 JCache 实现都没有超越这一点,但一个悬而未决的任务是决定一种机制来帮助缓解这个 JCache 设计缺陷。

再次感谢您报告此问题。与往常一样,如果您有任何其他问题或反馈要分享,请随时与我们联系。

于 2016-01-18T05:18:31.940 回答