Я пытаюсь выяснить, какую стратегию кеша 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.
Итак, какой способ лучше?
Спасибо заранее!