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

Мне трудно понять, когда 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 является одним из таких продуктов, и я думаю, что больше.