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

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

Семь видов режима транзакций Spring

Хотя распределенные транзакции в Spring обычно реализуются с использованием Java Transaction API и протокола XA, существуют и другие реализации. Наилучшая реализация зависит от типа ресурсов, которые использует ваше приложение, и от того, готовы ли вы идти на компромисс между производительностью, безопасностью, надежностью и целостностью данных. В ответ на эту типичную для Java проблему разработчик Spring Дэвид Сайер представит 7 реализаций распределенных приложений Spring, 3 из которых используют протокол XA, а остальные 4 используют другие реализации. (Средние баллы знаний)

Поддержка Spring Framework API транзакций Java (JTA) позволяет приложениямНет необходимости находиться в контейнере Java EEМожно использовать распределенные транзакции и протокол XA. Однако даже при такой поддержке издержки производительности XA по-прежнему значительны и могут быть ненадежными и сложными в управлении. Удивительно, однако, что приложения определенного типа могут полностью избежать использования XA для распределенных транзакций.

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

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

Распределенные транзакции и их атомарность

ОдинРаспределенная транзакцияЧасто содержит несколько ресурсов транзакций. Ресурсы транзакций относятся к соединению между реляционными базами данных и ПО промежуточного слоя сообщений. Типичный ресурс транзакции будет иметь что-то вродеbegin(),rollback(),commit()такой API. В Java транзакционный ресурс обычно представляется в виде экземпляра, предоставляемого базовой фабрикой соединений: в случае с базой данных этоConnectionобъект (поDataSourceпредоставляется) илиJava Persistence API(JPA)EntityManagerобъект; дляJava Message Service(JMS), этоSessionобъект.

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

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

Если база данных сообщает об ошибке при обновлении данных (например, о нарушении ограничения), идеальная последовательность взаимодействия выглядит следующим образом:

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

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

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

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

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

Полный протокол XA с двухфазной фиксацией (2PC)

Если вам необходимо убедиться, что транзакции вашей приложения могут быть восстановлены после времени простоя сервера (сбой сервера или отключение питания), то протокол Full XA является вашим единственным вариантом. В приведенном ниже примере, общий ресурс, используемый для синхронизации транзакций, представляет собой специальный менеджер транзакций, который координирует информацию о процессах с использованием протокола XA. В Java, с точки зрения разработчика протокол через JTAUserTransactionОбъекты разоблачены.

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

Если приложение построено на Spring, оно будет использоватьJtaTransactionManagerи декларативное управление транзакциями Spring, чтобы скрыть детали базовой синхронизации. Для разработчиков, использовать XA или нет, зависит от того, как настроены фабричные ресурсы: как они настроены в приложении.DataSourceЭкземпляры и менеджеры транзакций. Эта статья содержит пример приложения (atomikos-dbProject), который демонстрирует эту конфигурацию. Приложение толькоDataSourceМенеджеры экземпляров и транзакций основаны на XA или JTA.

Чтобы увидеть, как работает пример, запуститеcom.springsource.open.dbмодульные тесты ниже.MulipleDataSourceTestsКласс вставляет данные в два источника данных, а затем использует функцию поддержки интеграции Spring для отката транзакции, как показано в листинге 1:

Листинг 1. Откат транзакции

@Transactional
  @Test
  public void testInsertIntoTwoDataSources() throws Exception {

    int count = getJdbcTemplate().update(
        "INSERT into T_FOOS (id,name,foo_date) values (?,?,null)", 0,
        "foo");
    assertEquals(1, count);

    count = getOtherJdbcTemplate()
        .update(
            "INSERT into T_AUDITS (id,operation,name,audit_date) values (?,?,?,?)",
            0, "INSERT", "foo", new Date());
    assertEquals(1, count);

    // 数据的变更将在此方法退出后回滚

  }

потомMulipleDataSourceTestsОбе операции проверит полный откат, как показано в листинге 2:

Листинг 2. Проверка отката

@AfterTransaction
  public void checkPostConditions() {

    int count = getJdbcTemplate().queryForInt("select count(*) from T_FOOS");
    // 该数据变更已被测试框架回滚
    assertEquals(0, count);

    count = getOtherJdbcTemplate().queryForInt("select count(*) from T_AUDITS");
    // 由于 XA 的存在,该数据变更也被回滚了
    assertEquals(0, count);

  }

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

Оптимизация XA и 1PC

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

XA и окончательная стратегия ресурсов

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

Режим общих транзакционных ресурсов

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

Существует простой пример этого шаблона, который знаком многим, в компонентах объектно-реляционного отображения (ORM) иJDBCОбщая база данных между компонентамиConnection. Вот что происходит, когда вы используете менеджер транзакций Spring, который поддерживает такие инструменты ORM, какHibernate,EclipseLinkиJava Persistence API(ЯПА). Одну и ту же транзакцию можно безопасно использовать в компонентах ORM и JDBC, и это выполнение обычно реализуется с помощью метода уровня службы, который управляет транзакцией.

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

Не все провайдеры могут это сделать. Другой способ, который работает практически для всех баз данных, заключается в использованииApache ActiveMQОбмен сообщениями и настройка политик хранения на сервере Message Broker. Знание хитростей делает его очень простым в настройке. этой статьиshared-jms-dbПример проекта демонстрирует эту конфигурацию. Код приложения (в данном случае модульные тесты) не должен знать об использовании этого режима, поскольку он уже включен декларативно в конфигурации Spring.

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

Листинг 3. Проверка отката сообщений и обновлений базы данных

@AfterTransaction
public void checkPostConditions() {

  assertEquals(0, SimpleJdbcTestUtils.countRowsInTable(jdbcTemplate, "T_FOOS"));
  List<String> list = getMessages();
  assertEquals(2, list.size());

}

Наиболее важной особенностью этой конфигурации является стратегия сохраняемости ActiveMQ, которая соединяет систему обмена сообщениями источника бизнес-данных с одним и тем жеDataSource, Spring для получения сообщенийJmsTemplateЛоготип не менее важен. Чтобы настроить политику сохраняемости ActiveMQ, такую ​​как листинг 4:

Листинг 4. Конфигурация сохраняемости ActiveMQ

<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"
  depends-on="brokerService">
  <property vm://localhost?async=false" />
</bean>

<bean id="brokerService" class="org.apache.activemq.broker.BrokerService" init-method="start"
  destroy-method="stop">
    ...
  <property >
    <bean class="org.apache.activemq.store.jdbc.JDBCPersistenceAdapter">
      <property >
        <bean class="com.springsource.open.jms.JmsTransactionAwareDataSourceProxy">
          <property />
          <property />
        </bean>
      </property>
      <property  />
    </bean>
  </property>
</bean>

Spring для получения сообщенийJmsTemplateКонфигурация включенных флагов показана в листинге 5:

Листинг 5. Настройка транзакцийJmsTemplate

<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
  ...
  <!-- 这很重要... -->
  <property  />
</bean>

Если не установленоsessionTransacted=trueВызов API для транзакции сеанса JMS никогда не будет выполнен, а получение сообщения не будет возвращено. Важный момент здесь является специальный параметр в брокере встроенного сообщенийasync=falseи правильноDataSourceоболочки, они вместе гарантируют, что ActiveMQ и Spring используют одну и ту же транзакцию JDBC.Connection.

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


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