Как спроектировать глобальную распределенную транзакцию (без базы данных)?Может ли JTA использовать ни для одной транзакции БД? - PullRequest
16 голосов
/ 21 марта 2012

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

TaskA {подзадача1, подзадача2, подзадача3 ...}

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

Чтобы сделать это, я следую шаблону транзакции «Аудит пробной версии», чтобы получить запись для каждой подзадачи, чтобы TaskA могла узнать результаты работы подзадач, а затем принять решение об откате или принятии. Это звучит просто, однако, сложная часть состоит в том, как связать каждую подзадачу с глобальной транзакцией?

Когда запускается TaskA, запускается глобальная транзакция, о которой подзадача ничего не знает. Чтобы осознать подзадачу, я должен передать контекст транзакции каждому вызову подзадачи. Это действительно ужасно! Моя подзадача может либо выполняться в новом потоке, либо выполняться удаленно, отправляя сообщение через брокера AMQP, сложно консолидировать способ распространения контекста.

Я провел несколько исследований, таких как «Шаблоны транзакций - набор из четырех шаблонов, связанных с транзакциями», «Проверенные транзакции в среде асинхронной передачи сообщений», но ни одна из них не решила мою проблему. У них либо нет практического примера, либо они не решают проблему распространения контекста.

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

Является ли X / Open XA единственным решением для этого? Может ли здесь помочь JTA (я не изучал JTA, так как большинство вещей, связанных с ним, связано с транзакцией базы данных, и я использую Spring, я не хочу подключать к своему программному обеспечению еще один сервер приложений Java EE).

Может ли какой-нибудь эксперт поделиться со мной своими мыслями? спасибо.

Заключение

Арджан и Мартин дали действительно хорошие ответы, спасибо. Наконец, я не пошел по этому пути. После дополнительных исследований я выбрал другой шаблон " CheckPoint " 1 .

Изучив мое требование, я обнаружил, что намерение «Аудит шаблона пробной транзакции» состоит в том, чтобы узнать, к какому уровню была достигнута операция, и если она не удалась, я могу перезапустить ее в точке сбоя после перезагрузки некоторого контекста. На самом деле это не транзакция, она не откатила другие успешные шаги после сбоя. Это суть паттерна CheckPoint. Тем не менее, изучение распределенных транзакций заставляет меня узнать много интересного. Помимо того, что упоминали Арджан и Мартин. Я также предлагаю людям, копающимся в этой области, взглянуть на CORBA, который является известным протоколом для распределенной системы.

Ответы [ 3 ]

11 голосов
/ 22 марта 2012

Вы правы, вам нужна поддержка двухфазного принятия благодаря менеджеру транзакций XA, предоставленному JTA API.

Насколько я знаю, Spring не предоставляет саму реализацию менеджера транзакций. JtaTransactionManager делегирует только существующей реализации, обычно предоставляемой из реализаций JavaEE.

Таким образом, вам нужно будет подключить реализацию JTA к Spring для эффективной работы.Вот несколько предложений:

Затем вам нужно будет внедрить ваш менеджер ресурсов для поддержки двухфазной фиксации.В мире JavaEE он состоит из адаптера ресурсов, упакованного как архив RAR.В зависимости от типа ресурса, следующие аспекты должны быть прочитаны / реализованы:

В качестве примеров я рекомендую вам взглянуть на реализации для классическогопроблема "транзакции с файлами":

7 голосов
/ 22 марта 2012

Если вы хотите написать свой собственный транзакционный ресурс, вам действительно нужно внедрить XAResource и позволить ему присоединяться к текущей транзакции, обрабатывать запросы на подготовку и фиксацию от менеджера транзакций и т. Д.

Источники данных являются наиболее известными транзакционными ресурсами, но, как уже упоминалось, они не единственные. Вы уже упоминали о JMS-провайдерах. Разнообразные решения для кэширования (например, Infinispan) также являются транзакционными ресурсами.

Реализация XAResources и работа с частью нижнего уровня JTA API и еще более низким уровнем JTS (Java Transaction Service) - задача не для слабонервных. API-интерфейс может быть архаичным, и весь процесс едва документирован.

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

Наблюдение в подавляющем большинстве случаев означает, что эффекты действия присутствуют в базе данных. Почти каждый источник данных уже является транзакционным, так что сценарий использования полностью покрыт.

Другим заметным эффектом является то, было ли сообщение отправлено или нет, и это также полностью охватывается существующими решениями для обмена сообщениями.

Наконец, обновление (общекластерного) карты памяти является еще одним наблюдаемым эффектом, который также охватывается основными поставщиками кэша.

Существует остаток спроса на транзакционные эффекты при работе с внешними корпоративными информационными системами (EIS), и, как правило, производители таких систем предоставляют соединители с поддержкой транзакций.

Дрожь оставшихся вариантов использования настолько мала, что, очевидно, никто никогда особо не удосужился написать об этом много. Есть несколько блогов, которые освещают некоторые основы, но многое останется для ваших собственных экспериментов.

Попробуйте сами проверить, действительно ли вам действительно нужно идти по этому пути, и если ваша потребность не может быть удовлетворена одним из существующих транзакционных ресурсов.

0 голосов
/ 22 июля 2015

Вы можете сделать следующее (аналогично вашей стратегии контрольных точек):

  1. TaskA выполняется в (локальной) JTA-транзакции и пытается зарезервировать необходимые ресурсы, прежде чем делегировать ее подзадачам

  2. Вызовы подзадачи выполняются через JMS / XA: если шаг 1 завершится неудачно, ни одна подзадача никогда не будет запущена, а если шаг 1 зафиксирован, то вызовы JMS будут приниматься в каждой подзадаче

  3. Подзадачи (повторно) пытаются обработать свое сообщение вызова с установленным пределом максимальной повторной доставки JMS (см. Документацию поставщика JMS о том, как это сделать)

  4. Настройка «очереди недоставленных сообщений» для любых сбоев в 3.

Это работает при условии, что:

- повторение шага 3 имеет смысл

- для сообщений в очереди недоставленных сообщений требуется небольшое вмешательство человека

Если это неприемлемо, то есть также TCC: http://www.atomikos.com/Main/DownloadWhitepapers?article=TccForRestApi.pdf - это можно рассматривать как шаблон «резервирования» для услуг REST.

Надеюсь, это поможет

Guy

http://www.atomikos.com

...