У меня есть служба, которая вызывает внешнюю систему для извлечения каких-либо объектов по их внешнему идентификатору, а также для отправки их обратно для обновления. Вместо извлечения объектов по одному есть более общие методы назначения:Spring cache/jsr107: аргумент list/collection как часть ключа
public interface ExternalSystem {
List<ExternalDTO> getObjects(List<String> externalIds);
void updateObjects(List<ExternalDTO> updates);
}
Я хотел бы поставить кэш на вершине ExternalSystem звонков, потому что они являются весьма дорогостоящими.
В реализации службы я могу просто поставить пружинные аннотации:
@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 г etObjects ([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
UPD2. Вот что-то похожее на то, что я хочу, кроме того, что я положу в пары кэша String и ExternalDTO для каждого элемента в коллекции. element-level-caching-of-list-to-list
Да, и я уверен, что уже должны быть некоторые пользовательские реализации. Речь идет не только об изъятиях, см. Прилагаемые вопросы в «Обновлении». –
Просто любопытно: Сколько экземпляров ваше приложение обычно запрашивает сразу? Если вы не можете сделать это через массовый запрос, а один за другим, вы не сможете удовлетворить максимальные требования к задержке со своего клиента? Если вы пойдете на собственное решение: вы профилировали все свое приложение, и это оптимизация, которая будет иметь наибольшее влияние? Просто спрашиваю;) – cruftex
Это хороший вопрос, но даже если это выполнимо в моем случае, это может быть невыполнимо в других случаях. Итак, вопрос более общий, чем мой случай. Итак, я ищу какое-то многоразовое решение для таких случаев. Если я его не найду, я напишу свое и опубликую здесь :) –