it-roy-ru.com

Когда и как использовать hibernate кэш второго уровня?

У меня проблемы с пониманием, когда hibernate попадает в кэш второго уровня и когда он делает недействительным кеш.

Вот что я сейчас понимаю:

  • Кэш второго уровня хранит объекты между сеансами, область действия - SessionFactory
  • Вы должны указать, какие сущности кэшировать, ни одна сущность не будет кэширована по умолчанию
  • Кеш запросов хранит результаты запросов в кеше.

Что я не понимаю, так это

  • Когда hibernate попадает в этот кеш?
  • Допустим, я настроил кэш второго уровня, но не кеширование запросов. Я хочу кешировать своих клиентов, их 50000. Каким образом я могу получить клиентов из кэша?
  • Я предполагаю, что могу получить их по кешу по id. Это было бы легко, но также не достойно кеширования. Но что делать, если я хочу сделать некоторые расчеты со всеми моими клиентами. Допустим, я хочу показать список клиентов, тогда как мне получить к ним доступ?
  • Как бы получить всех своих клиентов, если кеширование запросов отключено?
  • Что произойдет, если кто-то обновит одного из клиентов?
    • Будет ли этот клиент признан недействительным в кеше или все клиенты будут признаны недействительными?

Или я думаю, что кэширование совершенно неправильно? Что было бы более целесообразным в этом случае для использования кэша второго уровня? В документации по гибернации не совсем понятно, как кеш работает в реальности. Есть только инструкции о том, как его настроить.

pdate: Итак, я пришел к выводу, что кэш второго уровня (без кеша запросов) будет полезен для загрузки данных по идентификаторам. Например, у меня есть пользовательский объект, который я хочу проверять на разрешения в каждом запросе в веб-приложении. Будет ли это хорошим случаем уменьшить доступ к базе данных, кэшируя пользователя в кеше второго уровня? Как если бы я сохранял идентификатор пользователя в сеансе или где угодно, и когда мне нужно было проверять разрешения, я бы загружал пользователя по его идентификатору и проверял разрешения.

82
palto

Прежде всего, давайте поговорим о кэше уровня процесса (или кэше 2-го уровня, как его называют в Hibernate). Чтобы это работало, вы должны

  1. настроить кеш провайдера
  2. скажите hibernate, какие сущности следует кэшировать (прямо в файле hbm.xml, если вы используете этот вид сопоставления).

Вы сообщаете провайдеру кэша, сколько объектов он должен хранить и когда/почему они должны быть признаны недействительными. Допустим, у вас есть сущности Book и Author, каждый раз, когда вы получаете их из БД, из БД будут выбраны только те, которые не находятся в кеше. Это значительно повышает производительность. Это полезно, когда:

  • Вы пишете в базу данных только через Hibernate (потому что ей нужен способ узнать, когда нужно изменить или сделать недействительными сущности в кеше)
  • Вы часто читаете объекты
  • У вас есть один узел, и у вас нет репликации. В противном случае вам нужно будет реплицировать сам кеш (использовать распределенные кеши, такие как JGroups), что увеличивает сложность и не так хорошо масштабируется, как приложения без совместного использования.

Так когда же работает кеш?

  • Когда вы session.get() или session.load() объект, который был ранее выбран и находится в кэше. Кэш-память - это хранилище, где ID является ключом, а свойства - значениями. Таким образом, только когда есть возможность поиска по идентификатору, вы можете исключить попадание в БД.
  • Когда ваши ассоциации загружаются лениво (или загружаются с помощью выбора вместо объединений)

Но это не работает, когда:

  • Если вы не выбираете по идентификатору. Опять же - кэш 2-го уровня хранит карту идентификаторов сущностей с другими свойствами (на самом деле он хранит не объекты, а сами данные), поэтому, если ваш поиск выглядит следующим образом: from Authors where name = :name, то вы не нажимаете на кеш.
  • Когда вы используете HQL (даже если вы используете where id = ?).
  • Если в вашем отображении вы установили fetch="join", это означает, что для загрузки ассоциаций объединения будут использоваться везде вместо отдельных операторов выбора. Кэш уровня процесса работает на дочерних объектах, только если используется fetch="select".
  • Даже если у вас есть fetch="select", но в HQL вы используете объединения для выбора ассоциаций - эти объединения будут выпущены сразу, и они перезапишут все, что вы указали в hbm.xml или аннотациях.

Теперь о Query Cache. Следует отметить, что это не отдельный кеш, а дополнение к кешу уровня процесса. Допустим, у вас есть организация Country. Это статично, поэтому вы знаете, что каждый раз, когда вы говорите from Country, будет один и тот же набор результатов. Это идеальный кандидат для кеша запросов, он будет хранить список идентификаторов сам по себе, и когда вы в следующий раз выберете все страны, он вернет этот список в кеш уровня процесса, а последний, в свою очередь, по очереди , будет возвращать объекты для каждого идентификатора, так как эти объекты уже хранятся в кэше 2-го уровня. Кэш запросов становится недействительным каждый раз, когда что-либо связанное с сущностью изменяется. Допустим, вы настроили from Authors для помещения в кеш запросов. Это не будет эффективно, поскольку Автор часто меняется. Поэтому вы должны использовать Query Cache только для более или менее статических данных.

91
Stanislav Bashkyrtsev
  • кэш 2-го уровня - это хранилище ключей-значений. Это работает, только если вы получаете свои сущности по идентификатору
  • кэш 2-го уровня становится недействительным/обновляется для каждой сущности, когда сущность обновляется/удаляется через спящий режим. Он не аннулируется, если база данных обновляется другим способом.
  • для запросов (например, список клиентов) используйте кеш запросов.

На самом деле полезно иметь распределенный кеш с ключом-значением - вот что такое memcached, и он поддерживает Facebook, Twitter и многие другие. Но если у вас нет поиска по идентификатору, то это будет не очень полезно.

38
Bozho

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

Ответ на ваш вопрос один за другим - вот мой ответ.

В. Когда hibernate попадает в этот кеш?

О. Кэш первого уровня связан с объектом сеанса . Кэш второго уровня связан с объектом фабрики сеансов . Если объект не найден в первом, то проверяется второй уровень.

В. Допустим, я настроил кэш второго уровня, но не кеширование запросов. Я хочу кешировать своих клиентов, их 50000. Каким образом я могу получить клиентов из кэша?

О. Вы получили ответ в своем обновлении. Также в кеше запросов хранится только список идентификаторов объекта, и эти объекты с их идентификаторами хранятся в том же кэше второго уровня. Так что если вы включите кеш запросов, вы будете использовать тот же ресурс. Аккуратно верно?

В. Я предполагаю, что могу получить их по кешу по идентификатору. Это было бы легко, но также не достойно кеширования. Но что делать, если я хочу сделать некоторые расчеты со всеми моими клиентами. Допустим, я хочу показать список клиентов, тогда как мне получить к ним доступ?

А. ответил выше.

В. Как мне получить всех моих клиентов, если кеширование запросов отключено?

А. ответил выше.

В. Что произойдет, если кто-то обновит одного из клиентов? Будет ли этот клиент признан недействительным в кеше или все клиенты будут признаны недействительными?

О. Hibernate понятия не имеет, но вы можете использовать сторонние IMDG/распределенные кэши, которые будут реализованы как кэш второго уровня гибернации , и сделать их недействительными. например TayzGrid один из таких продуктов, и я думаю, есть еще несколько.

11
Basit Anwer