java Spring缓存/jsr 107:列表/集合参数作为键的一部分

8zzbczxx  于 2023-01-19  发布在  Java
关注(0)|答案(2)|浏览(148)

我有一个调用外部系统的服务,通过它们的外部id来检索某种对象,并将它们提交回更新。而不是一个接一个地检索对象,有一个更通用的目的方法:

public interface ExternalSystem {
    List<ExternalDTO> getObjects(List<String> externalIds);

    void updateObjects(List<ExternalDTO> updates);
}

我想在ExternalSystem调用上放置一个缓存,因为它们的开销相当大。
在服务的实现中,我可以简单地放置spring注解:

@Cacheable("cache-external")
List<ExternalDTO> getObjects(List<String> externalIds) {} 

@CacheEvict(cacheNames="cache-external", allEntries=true)
void updateObjects(List<ExternalDTO> updates);

然而,如果externalId之间有很多交集,这样的缓存将表现得非常糟糕,即
1.调用#1 getObjects([1,2,3,4])-〉通过[1,2,3,4]键放置缓存
1.调用#2 getObjects([1,2,3,4,5])-〉通过[1,2,3,4,5]键放置缓存
1.调用#3 getObjects([6,7,8,9])-〉通过[6,7,8,9]键放置缓存
1.调用#4 updateObjects(1)-〉清除所有缓存,但第三个缓存不包含3
因此,问题是如何实现定制策略(我假设它是不可实现的开箱即用),该策略将只驱逐那些真正应该被驱逐的条目,并将使键以这样的方式该高速缓存中检索相交对象?

**更新。**我发现了两个类似的问题:

  1. spring-cache-abstraction-with-multi-value-queries
  2. using-spring-cache-on-methods-that-take-an-array-or-collection
  3. spring-cacheable-methods-with-lists

**Upd 2.**下面的代码与我想要的代码类似,不同之处在于我将为集合中的每个项放入String和ExternalDTO对的缓存中。element-level-caching-of-list-to-list

mpgws1up

mpgws1up1#

AFAIK注解是不可能的,你可以使用命令式API,它包含你需要的批量操作,例如Cache.getAll(keySet)Cache.removeAll(keySet)

wztqucjr

wztqucjr2#

对我来说,它在这个配置下工作得很好。这是我的代码的模糊版本。

@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]' ...

我的设置:/资源/ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
    <cache name="test"
           maxBytesLocalHeap="1M"
           timeToLiveSeconds="300"/>
</ehcache>

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"
    ...
}

相关问题