Spring cache / jsr107:列表/集合参数作为键的一部分 [英] Spring cache/jsr107: list/collection argument as part of the key
问题描述
我有一项服务,该服务调用外部系统以通过其外部ID检索某种对象并将其提交回进行更新。而不是一个个地检索对象,而是有一个通用的方法:
I have a service which calls external system to retrieve some kind of objects by their external id as well as submit them back to update. Rather than retrieving objects one by one there is a more generic purpose methods:
public interface ExternalSystem {
List<ExternalDTO> getObjects(List<String> externalIds);
void updateObjects(List<ExternalDTO> updates);
}
我想在ExternalSystem调用上放置一个缓存,因为它们相当
I would like put a cache on top of the ExternalSystem calls because they are quite expensive.
在服务的实现中,我可以简单地放入spring注释:
In the implementation of the service I can simply put spring annotations:
@Cacheable("cache-external")
List<ExternalDTO> getObjects(List<String> externalIds) {}
@CacheEvict(cacheNames="cache-external", allEntries=true)
void updateObjects(List<ExternalDTO> updates);
但是,如果我在externalId之间有很多交集,则这样的缓存将表现得很差,即
However, such a cache will behave very badly in case I have a lot of intersection between externalIds, i.e.
- 调用#1 getObjects([1,2,3,4])->由[1,2,3,4放置的缓存]键
- 调用#2 getObjects([1,2,3,4,5])->通过[1,2,3,4,5]键放置的缓存
- Call#3 getObjects([6,7,8,9])->通过[6,7,8,9]键放置的缓存
- Call #4 updateObjects( 1 )->逐出所有缓存,但第三个缓存没有t包含3
- Call#1 getObjects([1,2,3,4]) -> cache put by [1,2,3,4] key
- Call#2 getObjects([1,2,3,4,5]) -> cache put by [1,2,3,4,5] key
- Call#3 getObjects([6,7,8,9]) -> cache put by [6,7,8,9] key
- Call#4 updateObjects(1) -> evict all the caches but the third cache doesn't contain 3
因此,问题是如何实施自定义策略(我认为开箱即用)只会驱逐那些真正应该被驱逐的条目,并以使密钥能够从高速缓存中检索相交对象的方式来创建键?
So, the question is how to implement the custom strategy (I assume it's not doable out-of the box) which will evict only those entries which really should be evicted and will make the keys such a way that intersecting objects are retrieved from the cache?
已更新。 >我发现了两个类似的问题:
Upd. I've found two similar questions:
- spring-cache-abstraction-with-multi-value-queries
- using-spring-cache-on-methods-that-take-an-array-or-collection
- spring-cacheable-methods-with-lists
Upd2。
这与我想要的东西类似,除了我将为集合中的每个项目放入String和ExternalDTO缓存对中。
element-level-对列表进行缓存
推荐答案
对我来说,此配置可以正常工作。
这是我代码的混淆版本。
For me it worked fine with this config. This is a obfuscated version of my code.
@Cacheable(cacheNames = "test", key = "#p0")
public List<String> getTestFunction(List<String> someIds) {
getTestFunction(Arrays.asList("A","B","C"));
2020-04-02 15:12:35.492 TRACE 18040 --- [Test worker] o.s.cache.interceptor.CacheInterceptor : Computed cache key '[A, B, C]' for operation Builder[public java.util.List org.Main.getTestFunction(java.util.List)] caches=[test] | key='#p0' | keyGenerator='' | cacheManager='' | cacheResolver='' | condition='' | unless='' | sync='false'
您看到它隐含了字符串
... Computed cache key '[A, B, C]' ...
我的设置:
/resources/ehcache.xml
My setup: /resources/ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<cache name="test"
maxBytesLocalHeap="1M"
timeToLiveSeconds="300"/>
</ehcache>
gradle.build
gradle.build
plugins {
id "org.springframework.boot" version "2.2.4.RELEASE"
....
}
dependencies {
implementation "org.springframework.boot:spring-boot-starter-cache"
implementation "org.ehcache:ehcache:3.8.1"
...
}
这篇关于Spring cache / jsr107:列表/集合参数作为键的一部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!