Реализация распределенных транзакций Spring — с XA и без — часть 2

Java задняя часть Spring Программа перевода самородков

Ресурс общей базы данных иногда может быть синтезирован из существующих отдельных ресурсов, особенно если все они находятся на одной платформе СУБД. Все поставщики баз данных корпоративного уровня поддерживают концепцию синонимов (или эквивалентов), когда таблицы в одной схеме (терминология Oracle) определяются как синонимы в другой схеме. Таким образом, один и тот же клиент JDBC может получить доступ к физическим данным на платформе.ConnectionОбработка транзакции. Например, реализация шаблона Shared Transactional Resource в ActiveMQ в реальной системе (в отличие от этого) часто приводит к созданию синонимов как для обмена сообщениями, так и для бизнес-данных.

Производительность и JDBCPersistenceAdapter

Некоторые в сообществе ActiveMQ утверждаютJDBCPersistenceAdapterможет вызвать проблемы с производительностью. Однако многие проекты и системы реального времени используют ActiveMQ с реляционными базами данных. В этих случаях получен разумный совет — использовать версию журнала для повышения производительности. Это не относится к режиму общих ресурсов транзакций (поскольку журнал является новым ресурсом транзакций). Тем не менее, жюри отсутствуетJDBCPersistenceAdapter. и на самом деле есть основания полагать, что общие транзакционные ресурсы могутулучшать. Производительность находится на стороне ведения журнала. Это область активных исследований между инженерными командами Spring и ActiveMQ.

Другой метод совместного использования ресурсов для сценариев без сообщений (мультибаза данных) заключается в связывании двух схем базы данных вместе на платформе СУБД с использованием функции связывания Oracle Data (см. Ресурсы). Это может потребовать изменения кода приложения или создания синонимов, поскольку псевдонимы, ссылающиеся на имя таблицы связанной базы данных, содержат имя ссылки.

Режим однофазной фиксации с максимальной эффективностью

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

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

Чтобы помочь вам лучше понять схему и проанализировать последствия сбоя, я буду использовать в качестве примера обновления базы данных, управляемые сообщениями.

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

  1. Открыть транзакцию сообщения
  2. Получать сообщения
  3. начать транзакцию базы данных
  4. обновление базы данных
  5. Зафиксировать транзакцию базы данных
  6. зафиксировать транзакцию сообщения

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

  1. Открыть транзакцию сообщения
  2. начать транзакцию базы данных
  3. получить сообщение
  4. обновление базы данных
  5. Зафиксировать транзакцию базы данных
  6. зафиксировать транзакцию сообщения

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

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

Обратите внимание, что если фиксация ресурса базы данных не удалась, результатом будет откат. Таким образом, единственный неатомарный режим отказа — это когда первая транзакция фиксируется, а вторая транзакция откатывается. В более общем случае, если транзакция существуетnРесурс существуетn-1Такой режим отказа оставляет ресурс в несогласованном (зафиксированном) состоянии после отката. В случае использования базы данных сообщений следствием этого режима сбоя является откат сообщения и возврат его в другую транзакцию, даже если оно было успешно обработано. Таким образом, вы можете предположить, что самое худшее, что может случиться, это то, что могут быть доставлены дубликаты сообщений. В более общем случае, поскольку считается, что более ранние ресурсы в транзакции несут информацию о том, как будут обрабатываться более поздние ресурсы, конечный результат режима отказа часто можно назватьповтор сообщения.

Некоторые люди рискуют повторять сообщения настолько редко, что даже не удосуживаются предсказать их. Однако, чтобы быть более уверенным в правильности и согласованности ваших бизнес-данных, вам необходимо понимать их в своей бизнес-логике. Если вы знаете, что при бизнес-обработке могут возникать дубликаты сообщений, то все, что вам нужно сделать (обычно за дополнительную плату, но не так сильно, как 2PC), — это проверить, обрабатывались ли уже эти данные, и если да, не выполнять любое действие. Эту специализацию иногда называют шаблоном идемпотентного бизнес-сервиса.

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

Spring и управляемые сообщениями POJO

существуетобразец кодаизbest-jms-db project,Участники настраиваются с использованием основных параметров конфигурации, чтобы следовать шаблону однофазной фиксации с максимальной эффективностью. Идея состоит в том, что сообщения, отправленные в очередь, собираются асинхронными прослушивателями и используются для вставки данных в таблицы базы данных.

этоTransactionAwareConnectionFactoryProxy— компонент в Spring, предназначенный для работы с этим паттерном — это ключевой фактор. Используйте конфигурацию дляConnectionFactoryОбернут декоратором, который обрабатывает синхронизацию транзакций вместо того, который был предоставлен первоначальным поставщиком.ConnectionFactory. Это происходит, когдаjms-context.xml,Как показано в примере 6:

Пример 6. НастройкаTransactionAwareConnectionFactoryProxyпоставляется поставщиком упаковкиConnectionFactory

<bean id="connectionFactory"
  class="org.springframework.jms.connection.TransactionAwareConnectionFactoryProxy">
  <property>
    <bean class="org.apache.activemq.ActiveMQConnectionFactory" depends-on="brokerService">
      <property/>
    </bean>
  </property>
  <property/>
</bean>

ConnectionFactoryНет необходимости знать, с каким диспетчером транзакций выполнять синхронизацию, поскольку только одна транзакция активна, когда это необходимо, и Spring может обработать это внутренне. управляемая транзакцияdata-source-context.xmlНормально сконфигурировано вDataSourceTransactionManagerиметь дело с. Важно понимать, что компонентом менеджера транзакций является контейнер прослушивателя JMS, который будет опрашивать и получать сообщения:

<jms:listener-container transaction-manager="transactionManager">
  <jms:listener destination="async" ref="fooHandler" method="handle"/>
</jms:listener-container>

fooHandlerиmethodСообщите контейнеру слушателя, когда придет сообщениеasyncПри постановке в очередь какой компонент должен вызывать какой метод. Обработчик реализован так, принимаяStringкак входящее сообщение и использовать его для вставки записей:

public void handle(String msg) {

  jdbcTemplate.update(
      "INSERT INTO T_FOOS (ID, name, foo_date) values (?, ?,?)", count.getAndIncrement(), msg, new Date());

}

Для имитации ситуации сбоя в коде используетсяFailureSimulatorраздел. Он проверяет содержимое сообщения, чтобы увидеть, должно ли оно потерпеть неудачу и каким образом. как показано в примере 7maybeFail()метод вFooHandlerВызовите после обработки сообщения, но вызовите перед окончанием транзакции, чтобы он мог повлиять на результат транзакции:

Пример 7.maybeFail()метод

@AfterReturning("execution(* *..*Handler+.handle(String)) && args(msg)")
public void maybeFail(String msg) {
  if (msg.contains("fail")) {
    if (msg.contains("partial")) {
      simulateMessageSystemFailure();
    } else {
      simulateBusinessProcessingFailure();
    }
  }    
}

simulateBusinessProcessingFailure()метод выдает толькоDataAccessException, как если бы не удалось получить доступ к базе данных. При запуске этого метода вы ожидаете полного отката всех транзакций базы данных и сообщений. Этот сценарий находится в примере проектаAsynchronousMessageTriggerAndRollbackTestsПроверено в модульных тестах.

simulateMessageSystemFailure()подход путем ослабления базовой JMSSession来模拟消息传递系统中的失败。这里的预期结果是部分提交:数据库工作保持提交但消息回滚。 Это вAsynchronousMessageTriggerAndPartialRollbackTestsПроверено в модульных тестах.

Примеры пакетов также включены вAsynchronousMessageTriggerSunnyDayTestsМодульные тесты в классе, которые успешно фиксируют всю транзакционную работу.

Та же конфигурация JMS и та же бизнес-логика также могут использоваться в синхронной настройке, когда сообщения принимаются при блокировке вызовов в рамках бизнес-логики, а не делегируются контейнеру прослушивателя. Этот метод такжеbest-jms-dbПродемонстрировано в примере проекта. Случай солнечного дня и полный откатSynchronousMessageTriggerSunnyDayTestsиSynchronousMessageTriggerAndRollbackTestsтестировать.

Менеджер транзакций ссылок

Еще один пример шаблона однофазной фиксации с наилучшими усилиями (best-db-dbпроект), грубая реализация менеджера транзакций просто связывает список других менеджеров транзакций вместе для синхронизации транзакций. Если бизнес-процесс успешен, все они фиксируются, если нет, все откатываются.

реализовано вChainedTransactionManager, он принимает список других менеджеров транзакций в качестве внедренного свойства, как показано в примере 8:

Пример 8. Конфигурация ChainedTransactionManager

<bean id="transactionManager" class="com.springsource.open.db.ChainedTransactionManager">
  <property>
    <list>
      <bean
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property/>
      </bean>
      <bean
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property/>
      </bean>
    </list>
  </property>
</bean>

Эта конфигурация является самым простым тестом, чтобы вставить содержимое двух баз данных, откатиться и проверить, что две операции не оставляют следов. ЭтоMulipleDataSourceTestsМодульные тесты в реализации и пример XAatomikos-dbто же самое в проекте. Если откат не синхронизирован, но фиксация не удалась, тест не пройден.

Помните, что порядок ресурсов важен. Они вкладываются и фиксируются или откатываются в порядке, обратном их зачислению (это порядок в конфигурации). Это делает один из ресурсов особенным: если что-то пойдет не так, самый внешний ресурс всегда будет откатываться, даже если единственная проблема — отказ этого ресурса. также,testInsertWithCheckForDuplicates()Тестовый метод демонстрирует идемпотентный бизнес-процесс, защищающий систему от частичных сбоев. Он реализован как доступ к внутренним ресурсам (в данном случаеotherDataSource) Защитные проверки хозяйственных операций:

int count = otherJdbcTemplate.update("UPDATE T_AUDITS ... WHERE id=, ...?");
if (count == 0) {
  count = otherJdbcTemplate.update("INSERT into T_AUDITS ...", ...);
}

первое использованиеwhereПункт пытается обновиться. Если нет ответа, вставьте данные, которые вы хотите найти в обновлении. При этом стоимость допзащиты питания и т.п. это дополнительный запрос (обновление) в случае Солнечного дня. Эта стоимость будет очень низкой в ​​более сложных бизнес-процессах, каждый из которых выполняет множество запросов.

Если вы обнаружите ошибки в переводе или в других областях, требующих доработки, добро пожаловать наПрограмма перевода самородковВы также можете получить соответствующие бонусные баллы за доработку перевода и PR. начало статьиПостоянная ссылка на эту статьюЭто ссылка MarkDown этой статьи на GitHub.


Программа перевода самородковэто сообщество, которое переводит высококачественные технические статьи из Интернета сНаггетсДелитесь статьями на английском языке на . Охват контентаAndroid,iOS,внешний интерфейс,задняя часть,блокчейн,продукт,дизайн,искусственный интеллектЕсли вы хотите видеть более качественные переводы, пожалуйста, продолжайте обращать вниманиеПрограмма перевода самородков,официальный Вейбо,Знай колонку.