1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/mirrors-EasyTransaction

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
readme.md 43 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 14.03.2025 15:46 e558874

Английское описание

Русский

Ноль, SEO

Гибкие транзакции, распределённые транзакции, TCC, SAGA, надёжные сообщения, максимальные усилия доставки сообщений, транзакционные сообщения, компенсация, глобальные транзакции, soft transaction, distributed transaction, compensation, автоматическая компенсация

Этот фреймворк предназначен для решения проблем распределённых транзакций в SOA (включая микросервисы) одним пакетом.

Один, происхождение и особенности

Этот фреймворк был создан с учётом распределённых транзакционных сценариев, с которыми компания столкнулась ранее, а также презентации Чжэнь Ли из Алибабы "Обработка распределённых транзакций в больших SOA системах".

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

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

Особенности:* Введение JAR-пакета для использования, без необходимости отдельной установки координатора или ZooKeeper (при использовании extension-suite-database-starter)

  • Одна платформа для различных типов транзакций, что позволяет выполнять любую транзакцию
  • Возможность смешивания различных типов транзакций
  • Высокая производительность, большинство бизнес-систем ограничены базами данных, если не использовать функционал идемпотентности; дополнительная нагрузка на базу данных составляет всего одну запись размером 25 байт
  • Встроенный механизм идемпотентности и обработка случайного порядка вызова, значительно уменьшающая объем работы по разработке бизнес-логики, но увеличивающая количество записей в базе данных
  • Полностью независимый код бизнес-процессов
  • Поддержка вложенных транзакций
  • Распределенный ID транзакции может быть связан с бизнес-идентификатором, типом бизнеса, APPID, что облегчает мониторинг выполнения распределённых транзакций различными бизнес-процессами
  • Интеграция Seata AT режима, модификация блокировки строки для её локального хранения, преобразование центрального TC в распределённую модель ET## Два распределённых транзакционных сценария и соответствующие реализации фреймворка

Сценарии распределённых транзакций

  • Без использования распределённых транзакций
    • Самый часто используемый
    • Первый вариант выбора
  • Распределённые транзакции с использованием очередей сообщений для достижения конечной согласованности
    • Подходит для случаев, когда службы могут самостоятельно решать состояние глобальной транзакции (откат/подтверждение)
    • Часто встречается
    • При необходимости взаимодействия с другими службами через API, этот метод следует использовать в приоритетном порядке
    • В зависимости от того, гарантируется ли доставка сообщения подписчику, различаются надёжные сообщения и максимально усиливающиеся сообщения
    • Иногда бизнес требует асинхронных операций, которые должны вернуть результат синхронно. Если синхронное возвращение не удалось, то операция будет выполнена асинхронно в фоновом режиме. Эта бизнес-логика также относится к случаям, где нет необходимости в изменении внешних данных для завершения конечной согласованности, но поскольку требуется возврат результата синхронно, она отличается от надёжных сообщений.
  • Конечная согласованность с использованием традиционного компенсирующего механизма * Подходит для ситуаций, где требуется получение результатов удалённого выполнения для принятия решения о логической транзакции и возможность применения компенсации
    • Если использование очередей сообщений не решает проблему транзакции, следует рассмотреть применение конечной согласованности с использованием компенсации (если требуется вложенная транзакция, используется TCC)
    • В данном фреймворке традиционное компенсирование не поддерживает вложенные транзакции; если это необходимо, можно использовать TCC
  • Конечная согласованность с автоматическим компенсированием (интеграция и модификация AT-модели Alibaba Seata/Fescar)
    • Подходит для ситуаций, где требуется получение результатов удалённого выполнения для принятия решения о логической транзакции и допустимость периодического чтения и отображения грязных данных
    • В этом режиме обычный SELECT выполняется в состоянии грязного чтения. При выполнении локального обновления транзакции, если необходимые поля для логических проверок участвуют в глобальной транзакции, следует использовать AutoCpsLocalTransactionExecutor.executeWithGlobalLockCheck метод для получения точных значений с помощью SELECT FOR UPDATE перед проверкой * Из-за вышеупомянутого сотрудничества между глобальными транзакциями и локальными транзакциями, которое является скрытым и потенциально ошибочным, даже каждый SQL-запрос, связанный с обновлением, требует учета этого фактора. Поэтому при внедрении и использовании автоматического компенсирования важно установить соответствующие правила использования, чтобы избежать потери контроля над проектами в будущем.
    • Поскольку время достижения конечной согласованности значительно превышает время одиночной транзакции, производительность может существенно снижаться для записей, являющихся горячими данными и использующих автоматическое компенсирование.
  • Конечная согласованность с использованием TCC
    • Подходит для ситуаций, где требуется получение результатов удаленного выполнения для принятия решения о логической транзакции и невозможность применения компенсации.
    • Окончательное решение для всех обязательных сценариев использования 2PC. Наивысший объем кодирования и наибольшие затраты по производительности.
  • Saga
    • Похож на традиционное компенсирование (в некоторых фреймворках Saga определяется как традиционное компенсирование данного фреймворка). Этот фреймворк определяет SAGA так, что как положительные, так и отрицательные операции выполняются асинхронно через очередь, а не в рамках основной транзакции.Это позволяет сократить время блокировки записи транзакций.
  • В случае, когда большинство операций являются синхронными (например, TCC и компенсация), можно использовать SAGA для замены этих синхронных операций, что приведёт к повышению производительности.
  • Однако использование SAGA может потребовать небольших изменений в коде управления, поскольку основная транзакция должна быть разделена на две части (подробнее см. DEMO), что создаёт дополнительную нагрузку на программирование.
  • Реализация SAGA в данном фреймework не является традиционной версией SAGA. Её можно сравнить с асинхронным TCC, различие между которыми аналогично различиям между традиционной компенсацией и TCC.
  • Кроме того, данный фреймework использует RPC вместо очередей для реализации SAGA. Подробные причины можно найти в демонстрационном примере SAGA-TCC. О том, как выбрать распределённые формы транзакций, можно прочитать подробнее здесь: https://www.cnblogs.com/skyesx/p/9697817.html### Реализация в рамках и основные принципы работы Фреймворк реализует все вышеупомянутые сценарии транзакций и предоставляет унифицированный удобный интерфейс. Ниже приведены основные принципы реализации.

Распределённые транзакции не требуются

Для таких транзакций фреймворк вообще не вмешивается и не выполняет ни одной лишней строки кода.

Другие сценарии транзакций

Основной зависимостью фреймворка является Spring TransactionSynchronization. Любое используемое менеджер транзакций, который наследуется от AbstractPlatformTransactionManager, может использовать этот фреймворк (почти все менеджеры транзакций наследуются от этого базового класса). Кроме того, начиная с версии bk 1.0.0, фреймворк использует возможности конфигурации Spring Boot и новые возможности JDK 8, поэтому Spring Boot и JDK 8 также являются обязательными компонентами.Для распределённых транзакций фреймворк регистрирует соответствующие операции в TransactionSynchronization перед вызовом удалённого метода транзакции, например:

  • Для транзакций конечной согласованности, выполненных с помощью очередей сообщений, фреймворк отправляет сообщение после подтверждения глобальной транзакции, гарантируя, что внешние системы смогут видеть изменения только после успешного завершения транзакции. Это позволяет избежать необходимости писать код для управления состоянием "отправка — подтверждение — проверка" очередей.
  • Для транзакций конечной согласованности, выполненных с использованием TCC, фреймворк будет вызывать Confirm или Cancel в зависимости от фактического состояния транзакции. Аналогичная логика применяется к традиционным транзакциям с компенсацией.Фреймворк имеет фоновый поток для восстановления после аварийного прекращения работы (CRASH recovery). Он использует Write-Ahead Log, записанный до вызова распределённой службы, чтобы получить информацию о возможных уже выполненных бизнес-операциях, а также использует запись фреймворка, которая была подтверждена вместе с бизнес-транзакцией, чтобы определить конкретные действия CRASH (например, Confirm или Rollback для TCC).

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

  • Если бизнес-метод ещё не был вызван (или был вызван слишком поздно относительно метода компенсации), то метод компенсации также не будет вызван (хотя фреймворк всё равно отметит, что метод компенсации был вызван).
  • Если метод компенсации уже был вызван, то бизнес-метод больше не будет вызван, независимо от того, был ли он ранее вызван или нет. Результат всех удалённых вызовов возвращается в виде объекта Future, что предоставляет пространство для оптимизации производительности фреймворка. До первого получения результата все логи не записываются, а все удалённые методы не вызываются. Как только бизнес-программа пытается получить результат выполнения, логи пишутся в блок и последующие параллельные вызовы удалённых методов выполняются.Если бизнес-программа не пытается получить результат выполнения до COMMIT фреймворка, она попробует GET один раз для всех удалённых методов. В случае, если любой из удалённых методов выбрасывает исключение, фреймворк откатит бизнес-операцию перед окончательным COMMIT, независимо от того, был ли исключение перехвачен ранее. Это гарантирует простоту программной модели и позволяет легко писать правильный и понятный код.

3. Краткое руководство по использованию

Бизнес-код

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

<dependency>
    <groupId>com.yiqiniu.easytrans</groupId>
    <artifactId>easytrans-starter</artifactId>
    <version>1.4.3</version>
</dependency>

Starter включает несколько компонентов по умолчанию: распределённое управление транзакциями с использованием MySQL, RPC реализацию на основе Ribbon-Rest, сообщение очередей на основе Kafka. Если эти компоненты не нужны или требуется замена, их можно исключить.

Инициатор бизнес-процесса

Для инициатора бизнес-процесса фреймворк предлагает только один интерфейс:

public interface EasyTransFacade {
    /**
     * Начать распределённую транзакцию
     *
     * @param busCode appId + busCode + trxId — это глобально уникальный ID, независимо от того, будет эта транзакция завершена или отменена
     * @param trxId см busCode
     */
    void startEasyTrans(String busCode, String trxId);
}
``````markdown
/**
 * Выполнить удалённую транзакцию
 *
 * @param params
 * @return
 */
<P extends EasyTransRequest<R, E>, E extends EasyTransExecutor, R extends Serializable> Future<R> execute(P params);
}

Способ использования представлен ниже: используйте сторонний метод напрямую, не беспокоясь о конкретном типе распределённой транзакции или последующем процессе.

@Transactional
public void buySomething(int userId, long money) {
    /**
     * Локальный бизнес-метод, создание заказа и получение номера заказа
     */
    JdbcTemplate jdbcTemplate = util.getJdbcTemplate();
    Integer id = saveOrderRecord(jdbcTemplate, userId, money);

    /**
     * Объявление глобального ID транзакции, который состоит из appId, кода бизнес-процесса и внутреннего ID бизнес-процесса
     * Этот метод также можно не вызывать, в этом случае фреймворк использует по умолчанию код бизнес-процесса и автоматически сгенерированный ID
     * Однако недостатком такого подхода является то, что глобальный ID транзакции не может быть непосредственно связан с конкретной операцией бизнеса
     * Тем не менее, это можно исправить с помощью пользовательских BusinessCodeGenerator и TrxIdGenerator
     */
    transaction.startEasyTrans(BUSINESS_CODE, id);
}
``````java
/**
 * Вызов удаленного сервиса для списания необходимой суммы денег, этот удаленный сервис реализует TCC интерфейс
 * Фреймворк будет использовать результат транзакции метода buySomething для обеспечения конечной согласованности удаленного сервиса
 */
WalletPayTccMethodRequest deductRequest = new WalletPayTccMethodRequest();
deductRequest.setUserId(userId);
deductRequest.setPayAmount(money / 2);
// В бизнес-логике возможно многократное выполнение одного и того же метода, последний действительный вызов будет иметь эффект
Future<WalletPayTccMethodResult> deductFuture = transaction.execute(deductRequest);
Future<WalletPayTccMethodResult> deductFuture = transaction.execute(deductRequest);
}
#### Вызов удаленного сервиса для записи бухгалтерских данных, бухгалтерский сервис является компенсирующим сервисом
Когда метод `buySomething` откатывается в рамках транзакции, фреймворк автоматически вызывает соответствующий метод компенсации.
``````java
AccountingRequest accountingRequest = new AccountingRequest();
accountingRequest.setAmount(money);
accountingRequest.setUserId(userId);
Future<AccountingResponse> accountingFuture = transaction.execute(accountingRequest);

Отправка сообщения для триггеринга связанной бизнес-обработки, например, увеличение очков. Это надежное сообщение.

Это сообщение будет гарантировано отправлено после успешного завершения транзакции buySomething().

OrderMessage orderMessage = new OrderMessage();
orderMessage.setUserId(userId);
orderMessage.setAmount(money);
Future<PublishResult> reliableMessage = transaction.execute(orderMessage);

### Поставщик услуг
Для поставщика услуг следует реализовать соответствующие интерфейсы и зарегистрировать их в контейнере Bean Spring.

Например, для предоставления услуги TCC требуется реализация интерфейса `TccMethod`.

```java
public interface TccMethod<P extends TccTransRequest<R>, R extends Serializable> extends RpcBusinessProvider<P> {
    R doTry(P param);
    void doConfirm(P param);
    void doCancel(P param);
}

Конкретная реализация:

@Component
public class WalletPayTccMethod implements TccMethod<WalletPayTccMethodRequest, WalletPayTccMethodResult> {

    @Resource
    private WalletService walletService;

    @Override
    public WalletPayTccMethodResult doTry(WalletPayTccMethodRequest param) {
        return walletService.doTryPay(param);
    }

    @Override
    public void doConfirm(WalletPayTccMethodRequest param) {
        walletService.doConfirmPay(param);
    }

    @Override
    public void doCancel(WalletPayTccMethodRequest param) {
        walletService.doCancelPay(param);
    }
}

Где WalletPayTccMethodRequest — это запрос с параметрами, являющийся POJO, наследующимся от класса EasyTransRequest, и требующим аннотации BusinessIdentifier, чтобы фреймворк мог подтвердить ID бизнес-операции, связанной с данным запросом.```java @BusinessIdentifier(appId = Constant.APPID, busCode = METHOD_NAME) public class WalletPayTccMethodRequest implements TccTransRequest { private static final long serialVersionUID = 1L;

private Integer userId;

private Long payAmount;

}

Пример выше представлен в традиционной форме вызова. Безопасное использование выглядит следующим образом:

```java
@Transactional
public String покупать_что_то(int userId, long деньги) {

    int id = сохранить_запись_о_плате(jdbcTemplate, userId, деньги);

    // WalletPayRequestVO - это объект-значение (value object), который не имеет никаких наследований или аннотаций, кроме связанных свойств и методов GETTER/SETTER
    WalletPayRequestVO запрос = new WalletPayRequestVO();
    запрос.setUserId(userId);
    запрос.setPayAmount(деньги);

    // payService - это экземпляр интерфейса PayService, созданный с помощью фреймворка. Вызов этого метода завершает распределенную транзакцию.
    WalletPayResponseVO оплата = payService.оплатить(запрос);

    return "id:" + id + " заморожено:" + оплата.getFreezeAmount();
}
```

#### Дополнительные примеры
Для получения более подробных примеров обратитесь к коду в easytrans-demos. Здесь представлено простое описание кода.

Более полная конфигурация и связанные примеры можно найти в UT-тестах easytrans-starter, где используется MockService со всеми возможными сценариями транзакций и тестами различных ситуаций ошибок.

### Настройка запуска
Каждый исполняющийся бизнес-контейнер требует создания двух таблиц. Типы полей были изменены, поэтому если таблицы уже существуют, их следует переопределить.
```sql
-- используется для записи информации о том, была ли выполнена конечная бизнес-операция
-- p_ с префиксом указывает на id родительского транзакта, связанного с данным транзактом
-- при выполнении запроса SELECT FOR UPDATE, если запись с указанным id транзакта отсутствует, значит транзакт завершился ошибкой
-- наличие записи, но статус равен 0 указывает на успешное завершение транзакта, статус 1 указывает на провал транзакта (включая родительский и текущий)
-- наличие записи, но статус равен 2 указывает на неопределенность окончательного состояния транзакта
CREATE TABLE `executed_trans` (
  `app_id` smallint(5) unsigned NOT NULL,
  `bus_code` smallint(5) unsigned NOT NULL,
  `trx_id` bigint(20) unsigned NOT NULL,
  `p_app_id` smallint(5) unsigned DEFAULT NULL,
  `p_bus_code` smallint(5) unsigned DEFAULT NULL,
  `p_trx_id` bigint(20) unsigned DEFAULT NULL,
  `status` tinyint(1) NOT NULL,
  PRIMARY KEY (`app_id`, `bus_code`, `trx_id`),
  KEY `parent` (`p_app_id`, `p_bus_code`, `p_trx_id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8 COLLATE = utf8_bin;
```	CREATE TABLE `idempotent` (
	  `src_app_id` smallint(5) unsigned NOT NULL COMMENT 'Исходный AppID',
	  `src_bus_code` smallint(5) unsigned NOT NULL COMMENT 'Исходный тип бизнес-процесса',
	  `src_trx_id` bigint(20) unsigned NOT NULL COMMENT 'Исходный ID транзакции',
	  `app_id` smallint(5) NOT NULL COMMENT 'Вызов APPID',
	  `bus_code` smallint(5) NOT NULL COMMENT 'Вызов кода бизнес-процесса',
	  `call_seq` smallint(5) NOT NULL COMMENT 'Количество вызовов в рамках одного метода внутри одного транзакта',
	  `handler` smallint(5) NOT NULL COMMENT 'Обработчик appid',
	  `called_methods` varchar(64) NOT NULL COMMENT 'Названия вызываемых методов',
	  `md5` binary(16) NOT NULL COMMENT 'MD5 хэш параметров',
	  `sync_method_result` blob COMMENT 'Результат выполнения синхронного метода',
	  `create_time` datetime NOT NULL COMMENT 'Дата и время создания записи',
	  `update_time` datetime NOT NULL,
	  `lock_version` smallint(32) NOT NULL COMMENT 'Версия оптимистической блокировки',
	  PRIMARY KEY (`src_app_id`,`src_bus_code`,`src_trx_id`,`app_id`,`bus_code`,`call_seq`,`handler`)
	) ENGINE=InnoDB DEFAULT CHARSET=utf8; (Если используется REDIS для записи транзакционных логов, то следующие таблицы не требуются.) Для хранения транзакционных логов требуется база данных с двумя таблицами. Каждый бизнес-сервис должен иметь соответствующую базу данных для транзакционных логов. Несколько сервисов могут использовать одну общую базу данных, а один сервис может иметь отдельную базу данных для транзакционных логов.

```sql
CREATE TABLE `trans_log_detail` (
  `log_detail_id` int(11) NOT NULL AUTO_INCREMENT,
  `trans_log_id` binary(12) NOT NULL,
  `log_detail` blob,
  `create_time` datetime NOT NULL,
  PRIMARY KEY (`log_detail_id`),
  KEY `app_id` (`trans_log_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
```CREATE TABLE `trans_log_unfinished` (
  `trans_log_id` binary(12) NOT NULL,
  `create_time` datetime NOT NULL,
  PRIMARY KEY (`trans_log_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

SELECT * FROM translog.trans_log_detail;
```

Для использования автоматической компенсации потребуется создание двух дополнительных таблиц в бизнес-базе данных:

```sql
CREATE TABLE `undo_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `branch_id` bigint(20) NOT NULL,
  `xid` varchar(100) NOT NULL,
  `context` varchar(128) NOT NULL,
  `rollback_info` longblob NOT NULL,
  `log_status` int(11) NOT NULL,
  `log_created` datetime NOT NULL,
  `log_modified` datetime NOT NULL,
  `ext` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

CREATE TABLE `fescar_lock` (
  `t_name` varchar(64) NOT NULL,
  `t_pk` varchar(128) NOT NULL,
  `xid` varchar(256) NOT NULL,
  `create_time` datetime NOT NULL,
  PRIMARY KEY (`t_name`, `t_pk`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
```

Подробные конфигурации будут представлены в будущих руководствах, но до этого вы можете обратиться за примерами к тестовым случаям в easytrans-starter или воспользоваться демонстрационной версией. ## 4. Расширяемость
Фреймворк использует интерфейсы для соединения различных модулей, обеспечивая высокую степень расширяемости. Рекомендуются следующие модули для расширения и замены:* Реализация RPC
    * В настоящее время поддерживаются DUBBO, SPRING CLOUD RIBBON/EUREKA
    * Приветствуем добавление дополнительной реализации
* Реализация очередей сообщений
    * В настоящее время поддерживаются Alibaba ONS (при создании пожалуйста используйте незаконченные сообщения) и KAFKA
    * Приветствуем добавление дополнительной реализации; требуется реализовать два ключевых метода
* Реализация сериализации
    * В настоящее время используется сериализация Spring-core, которая менее эффективна, но производительность в данный момент не является бутылочным горлышком, поэтому нет необходимости в оптимизации
    * Приветствуем добавление дополнительной реализации для повышения эффективности
* Конкретные реализации классов Filter для добавления, удаления и изменения
    * В настоящее время доступны атомарные Filter, метаданные установочные FILTER, цепочка транзакций помощники
    * При наличии дополнительных требований можно добавить новые Filter
* Реализация выборщика источников данных
    * В настоящее время предоставляется одиночный выборщик источника данных
    * При наличии нескольких источников данных для услуги необходимо самостоятельно реализовать бизнес-ассоциированный выборщик источника данных, выбирающий источник данных в зависимости от запроса
* Реализация журнала выполнения транзакций    * В настоящее время предоставляются реализации на основе реляционных баз данных и Redis
     * Для повышения эффективности рекомендуется самостоятельно реализовать журнал транзакций на основе других форматов, таких как файловая система, HBase, приветствуем PR
 * Выборщик главного и вторичного сервера
     * Выбор главного и вторичного сервера на основе ZooKeeper
     * Выбор главного и вторичного сервера на основе MySQL
 * Кодировщик строк
     * Кодировка строк на основе ZooKeeper
     * Кодировка строк на основе MySQL
 * Генератор ID
     * Генерация снежинкового ID на основе ZooKeeper
     * Генерация снежинкового ID на основе MySQL

## 5. Наилучшие практики### Базирующиеся на журнале транзакций баз данных
* Размещайте журнал транзакций в отдельной базе данных от бизнес-базы данных

### Параметры и значения возврата
* Из-за затрат на сохранение данных, убедитесь, что параметры вызываемых методов и значения возврата минимальны


## 6. Часто задаваемые вопросы (FAQ)
1. Как определить после сбоя, был ли мягкий транзакт завершен?
   * При вызове метода `startEasyTrans()`, фреймворк вставляет запись в `executed_trans`
   * После вызова метода `startEasyTrans()` можно выполнять удалённые транзакционные методы
   * Инициатор операции (основной транзакт) будет владеть замком записи `executed_trans` до момента откатывания или завершения основного транзакта
   * Поэтому процесс восстановления после сбоя использует `select for update` для проверки записи `executed_trans`, всегда получая точный ответ о завершении транзакта (если основной транзакт всё ещё выполняется, `select for update` будет ждать)
   * Использование `select for update` позволяет избежать ошибочного получения конечного результата транзакта при использовании MVCC## 7. Совместимость версий внешних компонентов
* Если вы не используете `extensionsuite-database-starter` и вам требуется ZK, используйте версию ZK 3.4 или выше
* Интеграция SpringBoot 2.0.x и SpringCloud F версии см. пример `tcc-and-fescar` в Demo
    * Обратите внимание, что при создании документации последняя версия Spring Boot (2.0.8) включает багнутую версию `mysql-connector-java` (5.1.47), поэтому следует использовать 5.1.46
    * Также из-за изменения больших версий Spring Cloud некоторые пакеты могут поменять названия, поэтому при использовании ET Ribbon в F версии необходимо добавить `spring-cloud-starter-netflix-ribbon` в проект
* В случае проблем совместимости пакетов ZK, проверьте версии связанных пакетов в вашем проекте
    * С версии 1.2.0 `curator-recipes` и `curator-framework` должны быть версий 4.x.x, а клиентская версия ZooKeeper должна быть 3.4.x или 3.5.x (в зависимости от версии сервера ZK)
    * До версии 1.2.0 `curator-recipes` и `curator-framework` должны быть версий 2.x.x, а клиентская версия ZooKeeper аналогична## 8. Другое
Приглашение к автору через личный WeChat и официальный аккаунт

Официальный аккаунт

![официальный аккаунт WeChat](https://raw.githubusercontent.com/QNJR-GROUP/ImageHub/master/easytrans/wechat_public_account.jpg)

WeChat (при добавлении в WeChat укажите источник ET)

![WeChat](https://github.com/QNJR-GROUP/ImageHub/blob/master/easytrans/wechat.png?raw=true)

Если вам понравился фреймворк, пожалуйста, сделайте star, спасибо

email: skyes.xu@qq.com Написал несколько дополнительных статей о ET, пожалуйста, поставьте лайк, чтобы помочь SEO:

* Как выбрать распределённые формы транзакций: [https://www.cnblogs.com/skyesx/p/9697817.html](https://www.cnblogs.com/skyesx/p/9697817.html)
* "Некоторые распределённые транзакционные фреймворки" и "Мои предпочтения": [https://www.cnblogs.com/skyesx/p/10041923.html](https://www.cnblogs.com/skyesx/p/10041923.html)
* Сравнение архитектур Seata и EasyTransaction: [https://www.cnblogs.com/skyesx/p/10674700.html](https://www.cnblogs.com/skyesx/p/10674700.html)
* Анализ основных исходных кодов EasyTransaction (пожалуйста, прочтите сначала статью "Сравнение архитектур Seata", затем изучите код и процесс отладки демонстрационной программы): [https://www.cnblogs.com/skyesx/p/11111726.html](https://www.cnblogs.com/skyesx/p/11111726.html)

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/mirrors-EasyTransaction.git
git@api.gitlife.ru:oschina-mirror/mirrors-EasyTransaction.git
oschina-mirror
mirrors-EasyTransaction
mirrors-EasyTransaction
master