powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Вопрос по Spring @Cacheable
20 сообщений из 20, страница 1 из 1
Вопрос по Spring @Cacheable
    #39272172
RuslanGab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день!
Помогите пожалуйста решить такую задачу:

Есть отностилельно длительная операция чтения из БД. Читаются "все данные" за определенный промежуток времени (последние 3 месяца, последние полгода, прошлый год и т.п.).
Чтобы ускорить это узкое место (запись происходит очень редко - почти всегда чтение) я решил написать некий аналог кэша - это лист с полученными записями и две "даты" (с ... по ...), указывающие какие значения в нашем листе уже есть. Соответственно при получении запроса данные выбираются из имеющегося листа или если диапазон шире в него данные "довыбираются" из базы и опять же это хозяйство возвращается.
И тут внезапно я открыл для себя что спринг как всегда про все уже "подумал" и все уже написано, т.е. прочел про @Cacheable. Попробовал с небольшой entity - остался очень доволен результатом.
Однако @Cacheable вытягивает данные из кэша если запрос "повторяется", что совсем не то что мне нужно. Нужно чтобы если в кэше есть данные за последний месяц а зпрос пришел "за последние 2 месяца", то он "возвращал" имеющийся у него месяц и довыбирал данные за еще один (и оставлял "у себя" данные уже за 2 месяца). Решения такой задачи не нашел, но учитывая что я в Spring новичек думаю может и оно таки есть? Подскажите пожалуйста, люди добрые.
...
Рейтинг: 0 / 0
Вопрос по Spring @Cacheable
    #39272177
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
RuslanGab,

Смотри CacheResolver, CacheManager и Cache.
Тебе просто для этого случая нужно написать свою реализацию Cache, которая бы анализировала ключи и делала довыборку.
...
Рейтинг: 0 / 0
Вопрос по Spring @Cacheable
    #39272200
RuslanGab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Blazkowicz,

Спасибо! Вы мне не первый раз отвечаете, причем молниеносно:)
Теперь знаю куда копать - буду разбираться. Спасибо еще раз.
...
Рейтинг: 0 / 0
Вопрос по Spring @Cacheable
    #39272219
Фотография Паша01
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlazkowiczRuslanGab,

Смотри CacheResolver, CacheManager и Cache.
Тебе просто для этого случая нужно написать свою реализацию Cache, которая бы анализировала ключи и делала довыборку.

Вы действительно так быстро ответили. Как это у вас получилось? Вы быстро нагуглили или работали с этим?
...
Рейтинг: 0 / 0
Вопрос по Spring @Cacheable
    #39272222
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Паша01Вы действительно так быстро ответили. Как это у вас получилось? Вы быстро нагуглили или работали с этим?
Ну, по опыту, такие абстракции должны были существовать. Хорошие фреймверки позволяют написать свою реализацию на любом уровне.
Поэтому я открыл мануал на нужном разделе
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/cache.html
и быстро просмотрел, что такое возможно в принципе, а так же полистал классы в IDE.
...
Рейтинг: 0 / 0
Вопрос по Spring @Cacheable
    #39272223
Фотография Паша01
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Blazkowicz,

Здорово, вроде все кажется так просто)) Я уже начал подозревать, что под ником Blazkowicz скрывается целая компания программистов)))
...
Рейтинг: 0 / 0
Вопрос по Spring @Cacheable
    #39272258
RuslanGab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
BlazkowiczПаша01Вы действительно так быстро ответили. Как это у вас получилось? Вы быстро нагуглили или работали с этим?
Ну, по опыту, такие абстракции должны были существовать. Хорошие фреймверки позволяют написать свою реализацию на любом уровне.
Поэтому я открыл мануал на нужном разделе
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/cache.html
и быстро просмотрел, что такое возможно в принципе, а так же полистал классы в IDE.

Да опыт сила - никто наверное всего не знает и нужно погуглить/посмотреть время от времени, вот только человек с опытом знает куда смотреть и решение найдет сразу, а когда ты "вообще не в курсе" будешь копошиться целый день:(
...
Рейтинг: 0 / 0
Вопрос по Spring @Cacheable
    #39273629
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Интересно было бы увидеть такую реализацию кеша .
...
Рейтинг: 0 / 0
Вопрос по Spring @Cacheable
    #39274603
RuslanGab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Atum1Интересно было бы увидеть такую реализацию кеша .

Примерно так...

Код: java
1.
2.
3.
4.
5.
6.
7.
    @Transactional
    @Override
    @SuppressWarnings("unchecked")
    @Cacheable(cacheResolver = "customCacheResolver")
    public List<Anfrage> getEntitiesList(LocalDate fromDate, LocalDate toDate) {  
        ........     
    }



Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
public class CustomCacheResolver implements CacheResolver{        
    private static final String CACHE_NAME = "anfragenCache";
    private static LocalDate fromDate;
    private static LocalDate toDate;
    private static List<Anfrage> anfragen;

    @Autowired(required = true) private CacheManager cacheManager;
    @Autowired private AnfrageDAOInterface anfrageDAOInterface;

    @SuppressWarnings("unchecked")
    @Override
    public Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> cacheOperationInvocationContext) {
        // 1. Take dates and create new simple key
        LocalDate fromDateQuery = null;
        LocalDate toDateQuery = null;
        SimpleKey newKey;
        if (cacheOperationInvocationContext.getArgs().length == 2) { //optional - must always be from & to dates
            Object[] args = cacheOperationInvocationContext.getArgs();
            fromDateQuery = args[0] == null ? new LocalDate().minusYears(1000) : (LocalDate)args[0]; //null - all "in the past"
            toDateQuery = args[1] == null ? new LocalDate() : (LocalDate)args[1];                    //null - all "until today"
            newKey = new SimpleKey(args);            
            System.out.println("Key generated: " + newKey + ", date from: " + fromDateQuery + ", to: " + toDateQuery);
        } else {
            //Schould never be... DEFAULT work with cache if something wrong with arguments
            return new ArrayList<>(Arrays.asList(cacheManager.getCache(CACHE_NAME)));
        }
        
        // 2. Take cache
        EhCacheCache ehCache = (EhCacheCache)cacheManager.getCache(CACHE_NAME);  //this one we bringing back                
        
        Ehcache cache = (Ehcache)ehCache.getNativeCache();                       //and with this we working        
        // 3. Take cache back if we have it
        if (cache.getKeys().contains(newKey)) {
            return new ArrayList<>(Arrays.asList(ehCache));            
        // 4. "Create" cache if we don't have it
        } else {
            //we don't have anything -> execute query (NOT cachable!) and set dates                
                List<Anfrage> response = new ArrayList<>();


Тут далее выбираем данные из существующего кэша к примеру (ну надо знать в кэше с каким ключом они есть) и "довыбираем" уже некэшированными запросами из базы и т.п. Вариантов много и это уже дело техники - я реализовал и оно работает, но мне не очень нравится так что я это место не привожу буду переделывать немного иначе. Важно что в итоге мы "формируем" новый кэш и возвращаем его - таким образом запрос к базе получается "видит" что в кэше это уже есть и берет это а в базу не лезет. Профит в том что мы когда формировали "ответ" кэша или в базу вообще не лезли ("фильтровали" то что есть) или довыбирали данные частично, что много быстрее в моем случае. Плюшки от такой реализации а не решения "в лоб" с локальными переменнами - возможности конфигурирования размера, время жизни кэша и т.п.
Я конечно не профи может где не оптимально, но во всяком случае по скорости запросов (скажем было за последний год а я выбираю все - данные последнего года уже из базы не тянутся) прирост чувствуется. Как-то так..

Код: java
1.
2.
3.
4.
5.
6.
                ehCache.put(newKey, response);
            }   
            return new ArrayList<>(Arrays.asList(ehCache));
        }
    }
}
...
Рейтинг: 0 / 0
Вопрос по Spring @Cacheable
    #39276109
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
RuslanGab,

интересный подход , но много но ....

А почему вы не стали рассматривать решение на уровне БД ?

Хранить Временную талицу/ View - «материализованных представлений»

Мне почему-то кажется такой подход проще и логичнее ИМХО.


У вас задача сводится чисто к игре с датами - вам каждый раз нужно решать какой объем хранить в памяти - а что если выборка будет

за период смещенный на одни день влево /право - от дат вашего кеша? итд ... много сложных условий на перекрытие итд ....
...
Рейтинг: 0 / 0
Вопрос по Spring @Cacheable
    #39276249
RuslanGab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Atum1А почему вы не стали рассматривать решение на уровне БД ?
Хранить Временную талицу/ View - «материализованных представлений»

Согласен подход хороший. Конкретно в моем случае проблема в "узкости" скороcти базы, отчего я о решениях на уровне БД если честно даже и не думал...

Atum1У вас задача сводится чисто к игре с датами - вам каждый раз нужно решать какой объем хранить в памяти - а что если выборка будет
за период смещенный на одни день влево /право - от дат вашего кеша? итд ... много сложных условий на перекрытие итд ....

Тут не совсем согласен. Игра с датами - да. Однико при "смещении" вопрос решается довыборкой только за период смещения, что сравнительно быстро (во всяком случае у меня "прирост" скорости раза в два хотя все от "перодов" конечно зависит). Все "остальная" часть это тупой перебор коллекции, вытаскиваемой из кэша, что осушествляется практически мгновенно. При выборке более "узких" перодов многотысячные строки "выскакивают" в течение секунды. В целом я доволен.

Решения конечно могут быть разные я не претендую на однозначный "бэст практик", но в целом доволен. Не берусь судить было ли бы быстрее через уровень БД - не уверен. Проще - да согласен.
...
Рейтинг: 0 / 0
Вопрос по Spring @Cacheable
    #39276354
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
RuslanGab,

какая база медленная ? может просто построить индексы? оптимизировать запросы ? написать пару view и pl процедур ?

И так ваше решение :

Я правильно понял что у вас ключ в вашем кеше это дата_начала_идата_окончания диапазона ?!

и если вы попали во внутрь то вам повезло вы вытащили под коллекцию из кеша ...

Если вы не попали - и нет пересечений - у вас будет в кеше две коллекции
дата_начала_идата_окончания диапазона1
дата_начала_идата_окончания диапазона2

если у вас есть пересечение слева/справа с одним из диапазонов Вы делаете под выборку в базу и расширяете границы диапазона ?

сохраняя новый кеш
дата_начала_идата_окончания диапазона_новый границы.



Если я правильно описал алгоритм - то ,как мне кажется вам нужно просто предугадать диапазон дат ?

какой объем данных и сложность запросов на отчет ?

отчет не динамический ? ( данные это уже история и они не меняются ? так? - это Архив?)


тогда , как вариант вы можете заранее создать in memory data grids - и поместить в него все ваши отчеты постранично
... по месяцам, годам , дням ... (вопрос в доступном количестве памяти на сервере итд)

но это будет предпочтительнее что свой кеш на основе дат ?!

к Вашему кешу нужно написать АПИ

мониторинг , размера , актуальности данных, разрастания их в памяти итд ....

вывести все это в веб или другой ГУИ итд ...
...
Рейтинг: 0 / 0
Вопрос по Spring @Cacheable
    #39276404
RuslanGab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Atum1может просто построить индексы? оптимизировать запросы ?

С этого все начиналось. Первое сделано. Второе в "меру моих способностей" тоже.

Atum1RuslanGab,
И так ваше решение :
Я правильно понял что у вас ключ в вашем кеше это дата_начала_идата_окончания диапазона ?!
и если вы попали во внутрь то вам повезло вы вытащили под коллекцию из кеша ...
Если вы не попали - и нет пересечений - у вас будет в кеше две коллекции
дата_начала_идата_окончания диапазона1
дата_начала_идата_окончания диапазона2

Да все так.

Atum1если у вас есть пересечение слева/справа с одним из диапазонов Вы делаете под выборку в базу и расширяете границы диапазона ?
сохраняя новый кеш
дата_начала_идата_окончания диапазона_новый границы.

По сути дела почти так, но это как раз место которое мне не понравилось решительно, так что я доизвратился и ввел "пустой" кэш с ключом "маркер" (грубо говоря), а также локальный лист с моими сушностями. При запросах если кэш "маркер" не существует (прошло "время жизни", вытеснено) лист чистится. Этот лист "набивается" запросами (по логике там "пересечения" невозмижны, потому что "запрос" выполняется только когда кэша "маркер" нет и лист чистится, а в остальных случаях идут "подзапросы". Дальше идет перебор и выборка из этого листа. Единственное - в самих кэшированных данных уже образуются дубликаты, но их не должно быть много по логике работы приложения да и настройки EhCache позволяют общий объем сконфигурировать. Зато при повторных запросах имеющиеся в кэше данные соответственно вылетают сращу уже вообще без проверок и всего прочего.

Atum1какой объем данных и сложность запросов на отчет ?
отчет не динамический ? ( данные это уже история и они не меняются ? так? - это Архив?)
тогда , как вариант вы можете заранее создать in memory data grids - и поместить в него все ваши отчеты постранично
... по месяцам, годам , дням ... (вопрос в доступном количестве памяти на сервере итд)
но это будет предпочтительнее что свой кеш на основе дат ?!

Объем не очень большой. 20-30 тыс. При этом имеется много связанных по внешним ключам таблиц (9 если не ошибаюсь), данные из которых тоже надо "вытягивать" (а две из них и дальше связаны, причем отношениями один ко многим, и тоже надо "тянуть"). Так что в итоге производительность этого места оставляет желать лучшего. C View я если честно ускорения не смог увидеть - где был запрос 10 секунд там оно так и осталось (может если бы речь шла о минутах оно и было бы заметно).
Данные это уже история, и тем не менее они могут меняться (редактируемые). Однако это происходит очень редко и единично, так что в первом приближении можно их считать архивом.
Про memory data grids простите мне мою неопытность никогда не слышал - сейчас вот открыл статью на Хабре - интересно. Возможно это именно то что нужно - поизучаю пожалуй. Спасибо.
...
Рейтинг: 0 / 0
Вопрос по Spring @Cacheable
    #39276416
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
RuslanGabПро memory data grids простите мне мою неопытность никогда не слышал
если идти от БД или методов хранения, то:
-изучить план запроса и узкое его место (индексы)
-
https://ru.wikipedia.org/wiki/Материализованное_представление
- OLAP\OLTP
...
Рейтинг: 0 / 0
Вопрос по Spring @Cacheable
    #39276436
RuslanGab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А чем все же мое решение настолько плохо? Работает. Быстро. Я только за чтобы сделать лучше, но такой шквал критики:(
...
Рейтинг: 0 / 0
Вопрос по Spring @Cacheable
    #39276499
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
RuslanGabА чем все же мое решение настолько плохо? Работает. Быстро. Я только за чтобы сделать лучше, но такой шквал критики:(
ну уж прямо шквал. Не преувеличивайте.
Чем больше вариантов тем лучше.
Удачи!
...
Рейтинг: 0 / 0
Вопрос по Spring @Cacheable
    #39276737
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123RuslanGabПро memory data grids простите мне мою неопытность никогда не слышал
если идти от БД или методов хранения, то:
-изучить план запроса и узкое его место (индексы)
-
https://ru.wikipedia.org/wiki/Материализованное_представление
- OLAP\OLTP

+1

идти от БД

изучить план запроса - у любой БД есть инструмент для таких действий (самый простой mysql explain самый красивый у mssql )

Использовать средства БД именно Материализованное_представление ! обычное view это просто ваш запрос завернутый в фантик , он так же будет выполняться по времени - просто результат будет выдаваться в презентационном виде.


Почему критики - (мне решение нравится :) завидую что вам удалось так быстро разобраться с кешами , всеми этими ключами ,и аннотациями и написать свой кеш, не на каждой задаче возникает такая поребность, а тут реальное применение и хорошее решение)

Только свой велосипед - он с одной стороны всегда ближе и понятнее и 100% работает ... а чужой - он используется не только у вас:) и это дает некоторые гарантии ....

но в любом случае это опыт - написание своего кеша и опыт очень хороший .

+1
...
Рейтинг: 0 / 0
Вопрос по Spring @Cacheable
    #39276827
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мне кажется тут недоисследованы базовые возможности самой БД в части
mviews/OLAP.

За создание кастомного ресольвера конечно респект но КМК в топике
следует сравнить несколько разных решений. В противном случае
у нас всех складывается впечатление о какой-то безальтернативности.
...
Рейтинг: 0 / 0
Вопрос по Spring @Cacheable
    #39276944
RuslanGab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Боже мой, слава богу хоть здесь меня чему-то поучат! Это не сарказм. Обидно даже - на работе и спросить не у кого лишь бы работало а как и что... Сижу и тупею по ходу дела... Ладно это все лирика. За советы всем искренее спасибо. Буду изучать!
...
Рейтинг: 0 / 0
Вопрос по Spring @Cacheable
    #39276999
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
RuslanGabБоже мой, слава богу хоть здесь меня чему-то поучат! Это не сарказм. Обидно даже - на работе и спросить не у кого лишь бы работало а как и что... Сижу и тупею по ходу дела... Ладно это все лирика. За советы всем искренее спасибо. Буду изучать!

+1 задача решена = да
+1 Быстро = да
+1 Если есть время то можно и поковыряться в альтернативных решения = Да - а это расширение кругозора и возможностей :)
...
Рейтинг: 0 / 0
20 сообщений из 20, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / Вопрос по Spring @Cacheable
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]