-
Notifications
You must be signed in to change notification settings - Fork 1.2k
RedisCache synchronises all get(key, valueLoader) calls #2079
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I think we should be able to optimize and add synchronization only if the lookup yields |
Thanks. That's certainly easy. How do you feel about synchronising (in JVM) when loading values on a per key basis? |
Synchronizing on externally supplied keys is actually prone to create more problems than actually solve. We would need to maintain a decoupled copy and do proper housekeeping to evict keys as we do not have an in-memory reference backed by a cache like EhCache and others do. |
If we talk about single JVM locking it doesn't sound that complicated. I may be missing something though. |
There are two main issues why this isn't going to work with just a
We do not want to follow that way. A last note: When using a locking |
The previous version synchronize all calls to `get(key, valueLoader)`. After this PR the calls to value loader will only be synchronised if we do not have value for the given key. Improves spring-projects#2079
The previous version synchronize all calls to `get(key, valueLoader)`. After this PR the calls to value loader will only be synchronised if we do not have value for the given key. Fixes spring-projects#2079
Thanks for explanation. I understand your concerns, and they are very true in general case. I have no knowledge though if those cases, e.g. using unstable key generator happen in practice nor what a user would expect in such case.
Yes, AFAIK no one except RedisCache would hold on to a mutex, and thus it wouldn't stay in memory for much longer than needed. If the mutex is used in a lock by some thread, it wouldn't be evicted by GC, would it? I agree that there will be an increased memory usage. I think though that it will be relatively small, in general case, when compared to sizes of objects saved and received from cache. I don't have any data other than our project. However, in case of our project without such mechanism, we'll spend time waiting on locks, since all threads that which to compute a value for given key are processed in queue. Without per key locks, we need to do a workaround on our side.
Would you mind explaining how this helps one using |
I was examining the performance in our Spring Boot app. Based on profiling data, I noticed that we have a lot of wait times on
RedisCache#get(key, valueLoader)
method.The method signature makes it obvious why this is happening:
public synchronized <T> T get(Object key, Callable<T> valueLoader) {
In case of our app, it causes all cache lookups to be executed sequentially. (Admittedly a great protection for Redis server 😅).
In the past this method wasn't synchronized. It changed in this commit.
Documentation of the Cache interface states:
Technically speaking, the current synchronized implementation adheres to documentation. However, so would version that is not synchronized.
For comparison, here's how the
EhCacheCache
is implemented:I'm happy to submit a PR that changes the implementation. However, before doing so, I'd love to ask if the synchronized method was implemented in the current way deliberately and there's and edge case which makes changing it harder?
LV link
The text was updated successfully, but these errors were encountered: