Кэш L2 в Hibernate. Read-write или транзакционная стратегия параллелизма кэша на кластере?

Я пытаюсь понять, какую стратегию параллелизма кэша следует использовать для моего приложения (в частности, для обновления сущностей). Приложение представляет собой веб-сервис, разработанный с использованием Hibernate, развернуто на кластере Amazon EC2 и работает на Tomcat, поэтому сервера приложений там нет.

Я знаю, что существуют нестрогие-чтение-запись \ чтение-запись и транзакционные стратегии параллелизма кэша для обновляемых данных, и есть зрелые, популярные, готовые к производству 2L провайдеры кэша для Hibernate: Infinispan, Ehcache, Hazelcast.

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

Поэтому мой вопрос касается кэша чтения-записи. Безопасен ли он для кластеров? Гарантирует ли он синхронизацию данных между базой данных и кэшем, а также синхронизацию между всеми подключенными серверами? Или он подходит только для односерверных приложений, и я всегда должен предпочитать транзакционный кэш?

Например, если транзакция базы данных, обновляющая поле сущности (имя, фамилия и т.д.), завершилась неудачно и была откачена, будет ли чтение-запись кэш отбрасывать изменения или он просто передаст плохие данные (обновленное имя) на все остальные узлы? Требуется ли для этого транзакция JTA?

В теме Concurrency strategy configuration for JBoss TreeCache as 2nd level Hibernate cache говорится:

"READ_WRITE` - интересная комбинация. В этом режиме Hibernate сам работает как легкий XA-координатор, поэтому не требуется полноценного внешнего XA. Краткое описание того, как это работает:

  1. В этом режиме Hibernate сам управляет транзакциями. Все действия в БД должны быть внутри транзакции, режим автокоммита не работает.
  2. Во время выполнения flush() (которая может появляться несколько раз в течение транзакции, но обычно происходит непосредственно перед фиксацией) Hibernate проходит через сессию и ищет обновленные/вставленные/удаленные объекты. Затем эти объекты сначала сохраняются в базу данных, а затем блокируются и обновляются в кэше, чтобы параллельные транзакции не могут ни обновить, ни прочитать их.
  3. Если транзакция затем откатывается (явно или из-за какой-то ошибки), заблокированные объекты просто освобождаются и удаляются из кэша, чтобы другие транзакции могли читать и читать их. кэша, так что другие транзакции могут читать/обновлять их.
  4. Если транзакция успешно завершена, то заблокированные объекты просто освобождаются, и другие потоки могут читать/писать их.

Есть ли документация, как это работает в кластерной среде?

Кажется, что транзакционный кэш работает правильно, но для этого требуется среда JTA с отдельным менеджером транзакций (например, JBossTM, Atomikos, Bitronix), XA datasource и много изменений конфигурации и тестирования. Мне удалось развернуть это, но все еще есть некоторые проблемы с моими фреймворками. Например, Google Guice IoC не поддерживает транзакции JTA, и мне придется заменить его на Spring или перенести сервис на какой-нибудь сервер приложений и использовать EJB.

Так какой способ лучше?

Заранее спасибо!

14
задан Community 23 May 2017 в 11:54
поделиться