Кэш 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.
Лучший способ понять различия между этими стратегиями заключается в том, как они ведут себя во время вставки, обновления или удалить операции.
Вы можете проверить мой пост
здесь
который описывает различия в деталях.
Не стесняйтесь комментировать.