Description
Oliver Drotbohm opened SPR-9254 and commented
Imagine the following usage of the cache abstraction:
class MyComponent implements Component {
@Cacheable("myCache")
public Object myMethod(String key) {
}
}
Now assume the execution of myMethod(...)
takes a huge amount of time (hence the caching in the first place). Now futher assume we access the method concurrently with two threads. With the current implementation of the cache interceptor works as follows:
- thread 1 triggers the interceptor, we don't find a value for the key in the cache and thus invoke the method.
- Now while the method invocation in thread 1 runs, thread 2 enters the interceptor with the same key, we don't find a value and re-trigger the method call
This is unfortunate as the second invocation is entirely obsolete as the second thread could just wait for the first invocation to succeed and use the value returned. Beyond that we might face this scenario in extended version as while the first thread calculates the value pretty much all threads invoking the method with the same key would re-trigger the calculation. So the longer the value calculation takes the more likely we will run into unnecessary duplicate invocations of the method.
So what I am suggesting is that we should keep track of actual method invocations by key and block all concurrent accesses to that cache value until the first thread calculating it has finished and let the other threads use that value then. The CacheBuilder
API of the Google Guava project actually implements this out of the box.
Affects: 3.1.1
Issue Links:
- Provide some synchronization between @Cacheable and @CacheEvict annotated methods [SPR-9304] #13942 Provide some synchronization between
@Cacheable
and@CacheEvict
annotated methods - DATAREDIS-443 Support of synchronized mode introduced in Spring 4.3
- Support of ehcache's BlockingCache [SPR-11540] #16165 Support of ehcache's BlockingCache
- Better synchronization in ConcurrentMapCache [SPR-13810] #18383 Better synchronization in ConcurrentMapCache
- Allow @Cacheable method to return java.util.Optional variant of cached value [SPR-14230] #18804 Allow
@Cacheable
method to return java.util.Optional variant of cached value
Referenced from: commits spring-projects/spring-data-redis@1f97623, spring-projects/spring-data-redis@ceccafb, spring-projects/spring-data-redis@5cc5da9, spring-projects/spring-data-redis@a03c444
17 votes, 25 watchers