Когда и как использовать hibernate кэш второго уровня? - PullRequest
82 голосов
/ 14 августа 2011

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

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

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

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

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

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

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

Ответы [ 3 ]

91 голосов
/ 15 августа 2011

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

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

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

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

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

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

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

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

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

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

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

11 голосов
/ 17 декабря 2015

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

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

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

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

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

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

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

A.Ответ выше.

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

A.Ответ выше.

Q.Что будет, если кто-то обновит одного из клиентов?Будет ли этот клиент признан недействительным в кеше или все клиенты будут признаны недействительными?Hibernate не имеет ни малейшего представления, но вы можете использовать сторонние IMDG / распределенные кеши для реализации в виде hibernate второго уровня кеша и получить их недействительными.Например, TayzGrid является одним из таких продуктов, и я думаю, что есть и другие.

...