|
Spring @Cacheable впадает в бесконечный цикл
|
|||
---|---|---|---|
#18+
Доброго вечера! Не знаю, пользуется ли кто аннотациями спринговыми аннотациями @Cacheable или нет, но есть один очень важный нюанс: не стоит вызывать методы вот так: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9.
т.е. когда один метод с такой аннотацией вызывает другой метод с такой же аннотацией на том же кеше. Потому что внутри это приведет к вложенному вызову computeIfAbsent на одной и той же ConcurrentHashMap. Если выйдет так, что ключи сгенерируют hash, указывающий на одну и ту же корзину, то все это зависнет в бесконечном цикле в недрах ConcurrentHashMap. Т.е. например, вот такой код зациклится: Код: java 1.
все потому что строки "FB" и "Ea" возвращают одинаковый hash и соответственно попадут в одну корзину, и computeIfAbsent сносит башню от этого. Последствия такого кульбита - минус поток выполнения, да не просто залоченого, а в бесконечном цикле, что с моей точки зрения - просто катастрофа. ... |
|||
:
Нравится:
Не нравится:
|
|||
03.12.2019, 21:24 |
|
Spring @Cacheable впадает в бесконечный цикл
|
|||
---|---|---|---|
#18+
rabiter, если тебя послушать то можно подумать что ConcurrentHashMap имеет дефект коллизии хешей который приводит к зависанию. Ты это хотел сказать? ... |
|||
:
Нравится:
Не нравится:
|
|||
03.12.2019, 23:34 |
|
Spring @Cacheable впадает в бесконечный цикл
|
|||
---|---|---|---|
#18+
mayton, Да, это уже обсуждалось здесь: https://stackoverflow.com/questions/28840047/recursive-concurrenthashmap-computeifabsent-call-never-terminates-bug-or-fea и здесь на форуме https://www.sql.ru/forum/1206647/concurrenthashmap-mozhet-poymat-dedlok-pri-odnopotochnom-ispolzovanii Это не совсем дефект, потому что в документации к ConcurrentHashMap#computeIfAbsent можно найти следующее: Some attempted update operations on this map by other threads may be blocked while computation is in progress, so the computation should be short and simple, and must not attempt to update any other mappings of this map . Но я не про этот "дефект", а про то, во что он может вылиться, если вот так использовать вложенные вызовы @Cacheable аннотации. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.12.2019, 00:07 |
|
Spring @Cacheable впадает в бесконечный цикл
|
|||
---|---|---|---|
#18+
rabiter, ну ОК. Но наверное не стоит из кешируемого метода вызывать другой кешируемый. Убежден что в твоём коде можно зарефакторить общую логику и сделать к ней вызов из двух. Как бритва Оккама. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.12.2019, 00:12 |
|
Spring @Cacheable впадает в бесконечный цикл
|
|||
---|---|---|---|
#18+
Похоже в девятке пофиксили, ну как, просто бросают исключение теперь, а не уходят в бесконечный цикл. Но мало ли, я вот на 8-ке еще пока. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.12.2019, 00:14 |
|
Spring @Cacheable впадает в бесконечный цикл
|
|||
---|---|---|---|
#18+
mayton rabiter, ну ОК. Но наверное не стоит из кешируемого метода вызывать другой кешируемый. Убежден что в твоём коде можно зарефакторить общую логику и сделать к ней вызов из двух. Как бритва Оккама. Да да, все верно, так и придется делать. Есть еще один вариант, предложенный тут: https://github.com/ben-manes/caffeine/issues/89 Т.е. в мапу класть не результат выполнения, а CompletableFuture. Развязав таким образом CacheLoader от самого кеша (мапы). Но что-то рисковать нет желания) ... |
|||
:
Нравится:
Не нравится:
|
|||
04.12.2019, 00:18 |
|
Spring @Cacheable впадает в бесконечный цикл
|
|||
---|---|---|---|
#18+
mayton Но наверное не стоит из кешируемого метода вызывать другой кешируемый. в ТОМ же кеше. Смысл этого, мне совершенно не понятен ... |
|||
:
Нравится:
Не нравится:
|
|||
04.12.2019, 01:05 |
|
Spring @Cacheable впадает в бесконечный цикл
|
|||
---|---|---|---|
#18+
Leonid Kudryavtsev mayton Но наверное не стоит из кешируемого метода вызывать другой кешируемый. в ТОМ же кеше. Смысл этого, мне совершенно не понятен Ну смысл в том, чтобы создать некий фреймворк, которым могли бы пользоваться программисты "послабее" и не париться. Вот например пример: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
Тут оба метода кешируются в одном и том же кеше, который инвалидируется сразу как только справочник mime types изменяется. Ну тут понятно, что кешировать результат первого метода нет смысла - там нет ничего тяжелого, лишь выборка из списка. Но теперь, если все же кто-нибудь так напишет - нужна дополнительная защита - проверка в runtime, чтобы так Cacheable не использовали. Иначе словить бесконечный цикл, это просто дикость какая-то, не хотелось бы, это же катастрофа. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.12.2019, 02:30 |
|
Spring @Cacheable впадает в бесконечный цикл
|
|||
---|---|---|---|
#18+
Можно уточнить Если так Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
то это странно, тк запрос будет мимо кэша посколу ссылка прокси в действительности на реальный класс а не прокси. Leonid Kudryavtsevв ТОМ же кеше. Смысл этого, мне совершенно не понятен Тоже так же кажется как то странно даже звучит логически (ИМХО) Вот еще интересная тема с кэшами Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9.
Потратил много времени пока допер в чем проблема :=) ... |
|||
:
Нравится:
Не нравится:
|
|||
04.12.2019, 10:08 |
|
Spring @Cacheable впадает в бесконечный цикл
|
|||
---|---|---|---|
#18+
lleming Можно уточнить Если так Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
то это странно, тк запрос будет мимо кэша посколу ссылка прокси в действительности на реальный класс а не прокси. Не, я имел ввиду что все вызовы, конечно же, через прокси (я не совсем еще того) :-) ... |
|||
:
Нравится:
Не нравится:
|
|||
04.12.2019, 17:17 |
|
Spring @Cacheable впадает в бесконечный цикл
|
|||
---|---|---|---|
#18+
lleming Leonid Kudryavtsevв ТОМ же кеше. Смысл этого, мне совершенно не понятен Тоже так же кажется как то странно даже звучит логически (ИМХО) [/src] Ну это меня успокаивает, потому что уже как минимум два человека находят такие вызовы бессмысленными. Но опасность-то в том, что если кто-нибудь все-таки так напишет (ну не я, коллеги мои), то есть вероятность словить бесконечный цикл, а это минус поток. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.12.2019, 17:21 |
|
Spring @Cacheable впадает в бесконечный цикл
|
|||
---|---|---|---|
#18+
Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9.
А такой код уже не кажется таким бесмысленным? Т.к. я в кеш не с одним ключем лезу, а с разными (добавил префикс "Mr " + key)? Так вот если хеши у ключей на одну корзину укажут, то зациклится внутри ConcurrentHashMap ... |
|||
:
Нравится:
Не нравится:
|
|||
04.12.2019, 17:26 |
|
Spring @Cacheable впадает в бесконечный цикл
|
|||
---|---|---|---|
#18+
А зачем это кешировать? Код: java 1. 2. 3. 4.
Это идеальная быстро вычислимая pure-function в духе функнионального программирования. Твой пример - неудачен IMHO. Дай нам более приближенный к реальности. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.12.2019, 17:29 |
|
Spring @Cacheable впадает в бесконечный цикл
|
|||
---|---|---|---|
#18+
lleming Вот еще интересная тема с кэшами Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9.
Потратил много времени пока допер в чем проблема :=) Это потому что в спринге поумолчанию метод не участвует в генерации ключа :-) У себя я настроил генерацию ключа таким образом: составной ключ, который состоит из метода + параметры. Тогда получается что для этих двух методов будет разный ключ и соответственно две разные записи в кеше. И мой пример выше тоже получается обретает смысл, потому что эти два метода будут закешированы в одном кеше, но под разными ключами (методы-то разные, хоть и параметр один и тот же). ... |
|||
:
Нравится:
Не нравится:
|
|||
04.12.2019, 17:30 |
|
Spring @Cacheable впадает в бесконечный цикл
|
|||
---|---|---|---|
#18+
ну и не забываем. что сам по себе LRU подходить не для всех задач ! т.ч. у нормально пользователя может возникнуть желание, вместо LRU выбирать какой-то другой алгоритм (очистки кэша) смутные воспоминания, что mayton какой-то такой топик недавно создавал ... |
|||
:
Нравится:
Не нравится:
|
|||
04.12.2019, 17:49 |
|
Spring @Cacheable впадает в бесконечный цикл
|
|||
---|---|---|---|
#18+
mayton А зачем это кешировать? Код: java 1. 2. 3. 4.
Это идеальная быстро вычислимая pure-function в духе функнионального программирования. Твой пример - неудачен IMHO. Дай нам более приближенный к реальности. Ну да, эта конструкция не имеет смысла, конечно, потому что кешировать результат конкатинации конечно не имеет смысл... Давайте вот такой пример: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16.
Т.е. вот это уже может зациклиться. Workaround простой - использовать разные кеши. Но все же, за этим уже надо следить, а коллеги разные бывают. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.12.2019, 17:50 |
|
Spring @Cacheable впадает в бесконечный цикл
|
|||
---|---|---|---|
#18+
Вспомнился афоризм В компьютерных науках есть две сложности: инвалидация кэша, именование переменных. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.12.2019, 17:51 |
|
Spring @Cacheable впадает в бесконечный цикл
|
|||
---|---|---|---|
#18+
mayton Вспомнился афоризм В компьютерных науках есть две сложности: инвалидация кэша, именование переменных. Да да) про это я давно слышал ... |
|||
:
Нравится:
Не нравится:
|
|||
04.12.2019, 17:54 |
|
Spring @Cacheable впадает в бесконечный цикл
|
|||
---|---|---|---|
#18+
rabiter Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16.
Т.е. вот это уже может зациклиться. Workaround простой - использовать разные кеши. Но все же, за этим уже надо следить, а коллеги разные бывают. У тебя здесь по определению должны быть разные кеши. У тебя уникальный ключ для одной функции username + tenant а для другой - tenant. Это просто поинт к тому чтобы просто сделать НОРМАЛЬНЫЙ дизайн и проблема ликвидируется. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.12.2019, 17:54 |
|
Spring @Cacheable впадает в бесконечный цикл
|
|||
---|---|---|---|
#18+
Leonid Kudryavtsev ну и не забываем. что сам по себе LRU подходить не для всех задач ! т.ч. у нормально пользователя может возникнуть желание, вместо LRU выбирать какой-то другой алгоритм (очистки кэша) смутные воспоминания, что mayton какой-то такой топик недавно создавал Да, я читал этот топик. Но сейчас меня вопросы очистки не особо пока интересуют (у меня два варианта, как осуществлять очистку есть, чуть позже напишу. Но если кратко, это очистка по событию. И второй вариант - перед чтением кеша - проверка флага, который сбрасывается теми, кто меняют данные, и если флаг сброшен - то и кеш сбрасывается, прямо внутри аспекта). Но, кстати, может и правда использовать разные HashMap для разных методов? Но это будет забавно... Великоват overhead получается. Я думал использовать один ConcurrentHashMap, но к составному ключу просто добавить еще и метод (метод + параметры). И все просто валить в одну большую кучу. На самом деле кеш не будет очень большим в моем случае. Это больше попытка "навести порядок". Сейчас у нас куча полей в бинах типа ConcurrentHashMap или volatile DocumentTypes. Т.е. каждый бин кеширует сам у себя. Плюс такие бины подписаны на события по инвалидации кеша и сбрасывает эти поля просто по событию и все. И таких бинов довольно много. А так можно было бы просто аннотировать методы и все дела. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.12.2019, 18:04 |
|
Spring @Cacheable впадает в бесконечный цикл
|
|||
---|---|---|---|
#18+
Cц#$%ко, мое сообщение пропало ((( Нужно определиться, что же такое для нас КЭШ. Что понимать под этим термином? На мой взгляд: 1. Это соответствие параметр_ф-ции ==> результат Что для разных ф-ций БЕСМЫСЛЕННО. Если две ф-ции для одного и того же параметра. возврашают один и тот же результат - значит ф-ции совершенно одинаковые. Т.е. в продакшене это просто или копи-паст или переименование ф-ций. Обычно реализуется через структуры типа HashMap 2. Политика управления кэшем: размер, алгоритм очистки и прочее Обычно реализуется через LRU. Но НЕ всегда. Для некоторых применений LRU не лучшей вариант Таким образом, если мы хотим делать по хорошему: 1. HeshMap для каждой ф-ции должен быть СВОЙ 2. А вот LRU (или аналог) никто не запрешает делать один, на несколько HashMap'ов. Конечно, возможно, нужно кодировать IMHO & AFAIK 22032391 ... |
|||
:
Нравится:
Не нравится:
|
|||
04.12.2019, 18:19 |
|
Spring @Cacheable впадает в бесконечный цикл
|
|||
---|---|---|---|
#18+
rabiter Да, я читал этот топик..... сорри, пред сообщение это был кусок (продолжение) от сообщения выше почему-то сообщение не опубликовалось ((( ... |
|||
:
Нравится:
Не нравится:
|
|||
04.12.2019, 18:20 |
|
Spring @Cacheable впадает в бесконечный цикл
|
|||
---|---|---|---|
#18+
Leonid Kudryavtsev ну и не забываем. что сам по себе LRU подходить не для всех задач ! т.ч. у нормально пользователя может возникнуть желание, вместо LRU выбирать какой-то другой алгоритм (очистки кэша) смутные воспоминания, что mayton какой-то такой топик недавно создавал Да. Помню такое. Вот тут https://www.sql.ru/forum/1317932/chetvergovaya-invalidaciya-keshey ... |
|||
:
Нравится:
Не нравится:
|
|||
04.12.2019, 18:50 |
|
Spring @Cacheable впадает в бесконечный цикл
|
|||
---|---|---|---|
#18+
rabiter Это потому что в спринге поумолчанию метод не участвует в генерации ключа :-) А, так вот оно что Ну тогда понятно, в чём ошибка. Да, нужно разные кэши ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2019, 12:52 |
|
|
start [/forum/topic.php?fid=59&msg=39897882&tid=2120999]: |
0ms |
get settings: |
12ms |
get forum list: |
15ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
158ms |
get topic data: |
11ms |
get forum data: |
3ms |
get page messages: |
60ms |
get tp. blocked users: |
2ms |
others: | 244ms |
total: | 513ms |
0 / 0 |