Когда и как использовать спящий второй уровень кеша?
Мне трудно понять, когда hibernate попадает в кеш второго уровня и когда он делает недействительным кеш.
Это то, что я сейчас понимаю:
- Кэш второго уровня хранит объекты между сеансами, область действия - SessionFactory
- Вы должны указать, какие объекты будут кэшироваться, ни один объект не будет кэшироваться по умолчанию.
- Кэш запросов хранит результаты запросов в кеше.
То, что я не понимаю,
- Когда hibernate попадает в этот кеш?
- Скажем, я настроил кеш второго уровня, но не кеширование запросов. Я хочу кэшировать своих клиентов, из них 50000. Каким образом я могу получить клиентов из кеша?
- Я предполагаю, что могу получить их по id из кеша. Это было бы легко, но также не достойно кэширования. Но что, если я хочу сделать некоторые расчеты со всеми моими клиентами. Скажем, я хочу показать список клиентов, как я могу получить к ним доступ?
- Как я могу получить всех своих клиентов, если кеширование запросов отключено?
- Что произойдет, если кто-нибудь обновит одного из клиентов?
- Будет ли этот клиент недействителен в кеше или все клиенты будут признаны недействительными?
Или я думаю, что кэширование совершенно неверно? Что будет более подходящим использованием кеша второго уровня в этом случае? Документация спящего режима не совсем понятна, как работает кеш в действительности. Существуют только инструкции по настройке.
Update:
Поэтому я понял, что кеш второго уровня (без кеша запросов) будет полезен для загрузки данных по идентификаторам. Например, у меня есть объект пользователя, который я хочу проверить для разрешений в каждом запросе в веб-приложении. Будет ли это хорошим вариантом для сокращения доступа к базе данных путем кэширования пользователя во втором кеше второго уровня? Как я бы сохранил идентификатор пользователя в сеансе или где бы то ни было, и когда мне нужно проверить разрешения, я бы загрузил пользователя по его идентификатору и проверял разрешения.
Ответы
Ответ 1
Прежде всего, расскажите о кеше уровня процесса (или кеш второго уровня, как они его называют в Hibernate). Чтобы он работал, вы должны
- настроить поставщика кеша
- сообщите hibernate, какие объекты будут кэшировать (прямо в файле hbm.xml, если вы используете такой тип отображения).
Вы указываете провайдеру кеша, сколько объектов он должен хранить и когда/почему они должны быть признаны недействительными. Итак, скажем, у вас есть объекты Book и Author, каждый раз, когда вы получаете их из БД, только те, которые не находятся в кеше, будут выбраны из фактического БД. Это значительно повышает производительность. Это полезно, если:
- Вы записываете в базу данных только через Hibernate (потому что ему нужен способ узнать, когда нужно изменить или аннулировать сущности в кеше)
- Часто вы читаете объекты
- У вас есть один node, и у вас нет репликации. В противном случае вам придется реплицировать сам кеш (использовать распределенные кэши, такие как JGroups), который добавляет больше сложности, и он не масштабируется так же хорошо, как приложения без общего доступа.
Итак, когда работает кеш?
- Когда вы
session.get()
или session.load()
объект, который был ранее выбран и находится в кеше. Кэш - это хранилище, где ID - это ключ, а свойства - значения. Поэтому, только когда есть возможность поиска по ID, вы можете устранить попадание в БД.
- Когда ваши ассоциации ленивы загружены (или загружены с помощью выборок вместо соединений)
Но это не работает, когда:
- Если вы не выбрали по идентификатору. Снова - кэш второго уровня хранит карту идентификаторов объектов для других свойств (он фактически не хранит объекты, а сами данные), поэтому, если ваш поиск выглядит следующим образом:
from Authors where name = :name
, вы не попадаете в кеш.
- Когда вы используете HQL (даже если вы используете
where id = ?
).
- Если в вашем сопоставлении вы устанавливаете
fetch="join"
, это означает, что для загрузки ассоциаций объединения будут использоваться везде, а не в отдельных операторах select. Кэш уровня процесса работает с дочерними объектами, только если используется fetch="select"
.
- Даже если у вас есть
fetch="select"
, но затем в HQL вы используете объединения для выбора ассоциаций - эти соединения будут выданы сразу, и они будут перезаписывать все, что вы указали в hbm.xml или аннотации.
Теперь о Query Cache. Следует отметить, что это не отдельный кеш, это дополнение к кешу уровня процесса. Скажем, у вас есть страна. Это статично, так что вы знаете, что каждый раз будет тот же набор результатов, когда вы скажете from Country
. Это идеальный кандидат для кеша запросов, он сохранит список идентификаторов сам по себе, и когда вы в следующий раз выберете все страны, он вернет этот список в кеш уровня процесса, а последний, в свою очередь, вернет объекты для каждого идентификатора поскольку эти объекты хранятся уже в кеше второго уровня.
Кэш запросов недействителен каждый раз, когда все, что связано с сущностью, изменяется. Итак, скажем, вы настроили from Authors
для размещения в кэше запросов. Это не будет эффективно, поскольку автор часто меняет. Таким образом, вы должны использовать Query Cache только для более или менее статических данных.
Ответ 2
- кеш второго уровня - это хранилище ключей. Он работает только в том случае, если вы получаете свои объекты по id
- кеш второго уровня недействителен/обновляется для каждого объекта, когда объект обновляется/удаляется с помощью спящего режима. Он не является недействительным, если база данных обновляется по-другому.
- для запросов (например, список клиентов) используется кеш запросов.
В действительности полезно иметь распределенный кеш-ключ, который является memcached, и он активирует facebook, твиттер и многие другие. Но если у вас нет поисковых запросов по id, то это будет не очень полезно.
Ответ 3
Поздно к партии, но хотелось систематически ответить на этот вопрос, о котором спрашивают многие разработчики.
Принимая ваш вопрос один за другим, это мой ответ.
Q. Когда hibernate попадает в этот кеш?
а. Кэш первого уровня связан с объектом сеанса. Кэш второго уровня связан с Сессией Factory. Если объект не найден в первом, то проверяется второй уровень.
Q. Скажем, я настроил кеш второго уровня, но не кеширование запросов. Я хочу кэшировать своих клиентов, из них 50000. Каким образом я могу получить клиентов из кеша?
а. На это вы ответили. Кроме того, в кеше запросов хранится только список идентификаторов объекта, а те объекты w.r.t, что их идентификаторы хранятся в одном кэше второго уровня. Поэтому, если вы включите кеш запросов, вы будете использовать тот же ресурс. Правильно ли?
Q. Я предполагаю, что могу получить их по id из кеша. Это было бы легко, но также не достойно кэширования. Но что, если я хочу сделать некоторые расчеты со всеми моими клиентами. Скажем, я хочу показать список клиентов, как я могу получить к ним доступ?
а. Ответил выше.
Q. Как я могу получить всех моих клиентов, если кеширование запросов отключено?
а. Ответил выше.
Q. Что произойдет, если кто-нибудь обновит одного из клиентов? Будет ли этот клиент недействителен в кеше или все клиенты будут признаны недействительными?
а. Hibernate не имеет понятия, но вы можете использовать другие сторонние IMDG/распределенные кэши, которые будут реализованы как hibernate кеш второго уровня, и получить их недействительными. например TayzGrid является одним из таких продуктов, и я думаю, что больше.