- 
  Notifications
 You must be signed in to change notification settings 
- Fork 1.2k
Description
I noticed this issue when using Spring Boot Webflux (v3.4.10), Spring Framework (v6.2.11) and Spring Data Redis (v3.4.10).
Our service is using a Redis cache with support provided by Lettuce (v6.4.2.RELEASE).
The service uses the @Cacheable and @CacheEvict annotations with reactive support:
@Cacheable(RedisCacheConfig.IDs.ATTRIBUTES_CACHE) fun getAttributes(id: Identifier): Mono<List<Attribute>> = attributesService.getAttributesById(id) @CacheEvict(RedisCacheConfig.IDs.ATTRIBUTES_CACHE) fun evictAttributes(id: Identifier): Mono<Unit> = Mono.empty()
Calling code was evicting some keys if they happened to return an empty list:
 idList.associateWith { id ->
 attributesCache.getAttributes(id)
 .flatMap { attributes ->
 // evict cached attributes from redis if the attributes list is empty
 if (attributes.isEmpty()) {
 attributesCache
 .evictRelevantAssetAttributes(id)
 .then(Mono.just(attributes))
 } else {
 Mono.just(attributes)
 }
 }
 .awaitSingle()
 }We underestimated the number of times that we would be evicting cache entries and the service eventually became unresponsive and started logging errors due to 1 minute cache command timeouts (for get, store & evictions).
Digging into the problem we noticed that the number of blocking JVM threads spiked during this time. Using a debugger it is possible to trace the eviction flow and it looks like there is a blocking operation going on during cache eviction.
The Spring Framework is interacting through Spring Data Redis via the Cache interface which notes in the JavaDocs for the evict method:
If the cache is supposed to be compatible with CompletableFuture and reactive interactions, the evict operation needs to be effectively non-blocking, with any backend write-through happening asynchronously.
It looks like using Spring Data Redis with Lettuce supports async/reactive retrieve & store operations via the AsynchronousCacheWriterDelegate class.
However, it also looks like calls to evict a key use the synchronous cache writer via the DefaultRedisCacheWriter which blocks when invoking the del command via LettuceKeyCommands in LettuceConnection.
Is there a version / configuration of Spring Data Redis that supports async cache evictions? or is that functionality missing?