Кэш Hibernate L2. Кэш-память для чтения-записи или транзакционного кэша concurrency для кластера?

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

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

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

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

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

Конфигурация стратегии Concurrency для JBoss TreeCache как кэш-памяти Hibernate второго уровня гласит:

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

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

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

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

Итак, какой способ лучше?

Спасибо заранее!

Ответ 1

До сих пор я видел только кластерный 2LC, работающий с режимами транзакционного кэширования. Это то, что делает Infinispan, и на самом деле Infinispan до сих пор остался в стороне от реализации других режимов кэша concurrency. Чтобы облегчить транзакционное бремя, Infinispan интегрируется через синхронизацию транзакций с Hibernate в отличие от XA.

Ответ 2

Резюме различий

  • NonStrict R/w и R/w - это асинхронные стратегии, то есть они обновляются после завершения транзакции.
  • Транзакционный очевидно, синхронно и обновляется внутри транзакции.
  • Nonstrict R/w никогда не блокирует сущность, поэтому всегда есть шанс грязное чтение.
  • Чтение-запись всегда мягко блокирует сущность, поэтому любой одновременный доступ отправляется в базу данных. Однако существует удаленная вероятность того, что R/W может не производить повторную изоляцию Read.

Лучший способ понять различия между этими стратегиями  заключается в том, как они ведут себя во время вставки, обновления или  удалить операции.

Вы можете проверить мой пост здесь который описывает различия в деталях. Не стесняйтесь комментировать.