【发布时间】:2015-11-27 05:47:53
【问题描述】:
我正在使用带有 Guava 缓存的 Spring 缓存抽象。 我有一个带有@Cacheable 注释和参数(用作缓存键)的方法来将值放入缓存中。 但是这个方法是在多线程环境中访问的,所以对具有相同参数值的方法有多个并发调用。 所以这意味着创建要缓存的值的相同逻辑对同一个缓存键执行多次,并同时多次放入缓存中。 如果对于每个参数值(缓存键),该方法只调用一次并放入缓存一次,效率会更高。 Spring可以处理这样的场景吗?
【问题讨论】:
-
是否需要程序逻辑来初始化缓存,或者是否可以在应用程序上下文中配置缓存的条目?
-
您是否确认这确实发生了,或者您只是认为它是这样工作的?因为番石榴缓存不是那样工作的。该值被加载一次。 docs.guava-libraries.googlecode.com/git/javadoc/com/google/…: 如果另一个调用 get(K) 或 getUnchecked(K) 当前正在加载 key 的值,只需等待该线程完成并返回其加载的值
-
@JBNizet 我认为他担心多个线程调用
put并覆盖相同的键/值。我想知道这是否只是通过使用putIfAbsent(...) -
不幸的是,Spring 和 JSR-107 缓存注释都不会自动计算该值。相反,他们在 get-compute-put 上竞争。这是故意的,尽管我强烈反对并认为这是错误的推理。
-
@mike27 我搜索了 Spring 的问题跟踪器 SPR-11540,通过说 (1) 您应该将所有内容预加载到缓存中,以及 (2) 实现起来过于复杂,从而合理化了缺乏支持。两者都是无效的答案,因为最简单的方法是使用一个简单的锁数组,散列并锁定 get/put 调用(如果找到,则使用 get 外部绕过锁)。理想情况下,他们会委托缓存实现以获得更优化的版本。预加载整个世界违背了缓存的目的,恕我直言。
标签: java spring caching spring-cache google-guava-cache