我有一个服务,它调用外部系统通过它们的外部 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);
但是,如果我在 externalIds 之间有很多交集,那么这样的缓存会表现得很糟糕,即
- 调用#1 getObjects([1,2,3,4]) -> 缓存由 [1,2,3,4] 键放置
- 调用#2 getObjects([1,2,3,4,5]) -> 缓存按 [1,2,3,4,5] 键放置
- 调用#3 getObjects([6,7,8,9]) -> 缓存按 [6,7,8,9] 键放置
- 调用#4 updateObjects( 1 ) -> 驱逐所有缓存,但第三个缓存不包含 3
所以,问题是如何实现自定义策略(我认为它不是开箱即用的),它将只驱逐那些真正应该被驱逐的条目,并使键以这样的方式从缓存中检索相交对象?
更新。我发现了两个类似的问题:
- spring-cache-abstraction-with-multi-value-queries
- using-spring-cache-on-methods-that-take-an-array-or-collection
- spring-cacheable-methods-with-lists
更新2。 这是与我想要的类似的东西,除了我将为集合中的每个项目放入 String 和 ExternalDTO 的缓存对。 列表到列表的元素级缓存