В прошлой статье "Эти решения для распределенных транзакций" я упомянул три общих решения для распределенных транзакций, но нет конкретной реализации кода. Несколько друзей оставили сообщение, что они знают принцип, но до сих пор не пишут код , то в этой статье будет кратко рассказано об использовании кода для реализации двухфазной фиксации на основе протокола транзакций XA.
Перед конкретной демонстрацией давайте добавим немного знаний о транзакциях XA:Модель DTP и спецификация XA.
Модель DTP и спецификация XA поддерживаются X/Open, которая теперь является открытой группой, официальным веб-сайтом:http://www.opengroup.org/
. Открытая группа является независимой организацией, ответственной за разработку различных отраслевых технических стандартов. Поддерживается крупными известными компаниями или производителями, в основном следующими компаниями:
В настоящее время в открытой группе восемь компаний, и Huawei — одна из них. Что касается распределенной обработки транзакций (DTP), X/Open в основном предоставляет следующие справочные документы:
- Эталонная модель DTP:Пабы.open group.org/онлайн-пабы/...
- Спецификация DTP XA:pubs.open group.org/онлайн-пабы/…
Модель ПДП
В 3-м издании «Распределенная обработка транзакций: эталонная модель» указаны 5 основных элементов, составляющих модель DTP:
- Прикладная программа (AP для краткости): используется для определения границ транзакций (то есть определения начала и конца транзакций) и работы с ресурсами в пределах границ транзакций, что можно просто понимать как наше приложение.
- Менеджер ресурсов (Resource Manager, сокращенно RM): такие как базы данных, файловые системы и т. д., и обеспечивают способ доступа к ресурсам.
- Менеджер транзакций (Менеджер транзакций, именуемый ТМ): отвечает за назначение уникального идентификатора транзакции, отслеживание хода выполнения транзакции, а также за отправку и откат транзакции.
- Менеджер по коммуникационным ресурсам (CRM): Управляет обменом данными между распределенными приложениями в домене TM или между доменами TM.
- Протокол связи (CP): Предоставляет базовую службу связи между распределенными узлами приложений, предоставляемую CRM.
Дополнительные сведения об элементах модели DTP см. в документации opengroup. Далее поговорим об экземплярах DTP. Экземпляр DTP содержит не менееAP, RM, TMтри части. Как показано ниже:
Мы видим, что существует взаимодействие между AP, RM и TM, Общий процесс выглядит следующим образом:
- AP получает ресурсы базы данных от RM Лично я думаю, что это можно просто понимать как ссылку на базу данных, точно так же, как наше обычно используемое соединение для передачи данных.
- Менеджер ресурсов транзакций TM отвечает за присвоение уникального идентификатора транзакции, мониторинг процесса выполнения транзакции, а также за фиксацию и откат транзакции. AP привяжет свои собственные транзакции к TM, а остальные предоставит TM.
- TM сообщает RM (конкретная база данных, например MySQL), выполнять ли откат или фиксацию на основе собранных результатов.
Так что же такое протокол XA?? Спецификация XA предназначена для определения интерфейса взаимодействия. Как видно из приведенного выше рисунка, во всем DTP имеется три интерфейса взаимодействия. Спецификация XA в основном находится между TM и RM. Следующая картинка лучше для понимания:
Ну, так много о модели DTP и спецификации XA, вы можете проверить документы, предоставленные opengroup для получения подробной информации Давайте использовать знакомую базу данных MySQL для реализации двухэтапной фиксации протокола транзакций XA.
MySQL поддерживает распределенные транзакции XA, начиная с версии 5.0.3, и поддерживается только механизмом хранения InnoDB. Введите изображение ниже:
На официальном сайте базы данных MySQL есть модуль, посвященный транзакциям XA.
Больше ничего не скажу, здесь упомяну статус транзакции XA, полный процесс транзакции выглядит следующим образом:
- 1. Используйте XA START, чтобы запустить транзакцию XA и поместить ее в
ACTIVE
условие. - 2. Для транзакции XA в состоянии ACTIVE мы можем выполнить операторы SQL, составляющие транзакцию, а затем выполнить оператор XA END. XA END помещает транзакцию в
IDLE
условие. - 3. Для
IDLE
Транзакции состояния XA, которые могут выполнять оператор XA PREPARE или оператор XA COMMIT…ONE PHASE:- XA PREPARE помещает транзакцию в
PREPARED
условие. Оператор XA RECOVER в этот момент будет включать значение xid транзакции в свои выходные данные, поскольку XA RECOVER перечисляет все транзакции XA, которые находятся в состоянии PREPARED. - XA COMMIT…ONE PHASE используется для подготовки и фиксации транзакций. Значение xid не будет указано XA RECOVER, поскольку транзакция завершена.
- XA PREPARE помещает транзакцию в
- для
PREPARED
В транзакциях XA с отслеживанием состояния можно выполнить оператор XA COMMIT, чтобы зафиксировать и завершить транзакцию, или выполнить оператор XA ROLLBACK, чтобы откатить и завершить транзакцию.
Подводя итог, транзакции XA,Запустите транзакцию XA через Start и установите ее в активное состояние.Транзакция в активном состоянии может выполнять операторы SQL, а транзакция XA устанавливается в метод END через метод END.IDLE
условие. вIDLE
Состояние может выполнять операцию PREPARE или операцию COMMIT…ONE PHASE, которая является первой фазой двухфазной фиксации, а транзакция XA в состоянии PREPARED может выполнять фиксацию или RollBack, которая является второй фазой двухэтапной фиксации. совершить..
Вы могли заметить, что выше есть значение XID.Коротко, MySQL использует xid в качестве идентификатора для ветви транзакции. О xid определено в спецификации XA, спецификация XA определяет, что xid состоит из 4 частей:
- gtrid: глобальный идентификатор транзакции, длина которого не может превышать 64 байта.
- bqual: квалификатор ветвления (branch qualifier), максимум не может превышать 64 байта.
- data: значение xid, которое является содержимым после объединения gtrid и bqual.
- formatId: Функция formatId заключается в записи формата gtrid и bqual, подобно функции поля flags в memcached.
Ну, так много BB о транзакциях XA.Далее мы реализуем двухфазную фиксацию на основе протокола транзакций XA на примере.
Сцены:Чтобы имитировать комбинацию наличных и оплаты в красном конверте, предположим, что мы покупаем что-то за 100 юаней, платим 90 юаней наличными и платим 10 юаней в красных конвертах.Наличные и красные конверты находятся в разных хранилищах.
Предполагать:Теперь есть две библиотеки: xa_account (библиотека аккаунтов, кассовая библиотека), xa_red_account (библиотека красных конвертов). Под двумя библиотеками есть таблица account, а поля в таблице account относительно простые, всего три поля: id, user_id и balance_amount, SQL выкладывать не буду.
Ну, конкретный код выглядит следующим образом:
public class XaDemo {
public static void main(String[] args) throws Exception{
// 是否开启日志
boolean logXaCommands = true;
// 获取账户库的 rm(ap做的事情)
Connection accountConn = DriverManager.getConnection("jdbc:mysql://106.12.12.xxxx:3306/xa_account?useUnicode=true&characterEncoding=utf8","root","xxxxx");
XAConnection accConn = new MysqlXAConnection((JdbcConnection) accountConn, logXaCommands);
XAResource accountRm = accConn.getXAResource();
// 获取红包库的RM
Connection redConn = DriverManager.getConnection("jdbc:mysql://106.12.12.xxxx:3306/xa_red_account?useUnicode=true&characterEncoding=utf8","root","xxxxxx");
XAConnection Conn2 = new MysqlXAConnection((JdbcConnection) redConn, logXaCommands);
XAResource redRm = Conn2.getXAResource();
// XA 事务开始了
// 全局事务
byte[] globalId = UUID.randomUUID().toString().getBytes();
// 就一个标识
int formatId = 1;
// 账户的分支事务
byte[] accBqual = UUID.randomUUID().toString().getBytes();;
Xid xid = new MysqlXid(globalId, accBqual, formatId);
// 红包分支事务
byte[] redBqual = UUID.randomUUID().toString().getBytes();;
Xid xid1 = new MysqlXid(globalId, redBqual, formatId);
try {
// 账号事务开始 此时状态:ACTIVE
accountRm.start(xid, XAResource.TMNOFLAGS);
// 模拟业务
String sql = "update account set balance_amount=balance_amount-90 where user_id=1";
PreparedStatement ps1 = accountConn.prepareStatement(sql);
ps1.execute();
accountRm.end(xid, XAResource.TMSUCCESS);
// 账号 XA 事务 此时状态:IDLE
// 红包分支事务开始
redRm.start(xid1, XAResource.TMNOFLAGS);
// 模拟业务
String sql1 = "update account set balance_amount=balance_amount-10 where user_id=1";
PreparedStatement ps2 = redConn.prepareStatement(sql1);
ps2.execute();
redRm.end(xid1, XAResource.TMSUCCESS);
// 第一阶段:准备提交
int rm1_prepare = accountRm.prepare(xid);
int rm2_prepare = redRm.prepare(xid1);
// XA 事务 此时状态:PREPARED
// 第二阶段:TM 根据第一阶段的情况决定是提交还是回滚
boolean onePhase = false; //TM判断有2个事务分支,所以不能优化为一阶段提交
if (rm1_prepare == XAResource.XA_OK && rm2_prepare == XAResource.XA_OK) {
accountRm.commit(xid, onePhase);
redRm.commit(xid1, onePhase);
} else {
accountRm.rollback(xid);
redRm.rollback(xid1);
}
} catch (Exception e) {
// 出现异常,回滚
accountRm.rollback(xid);
redRm.rollback(xid1);
e.printStackTrace();
}
}
}
Запустив программу, вы можете увидеть следующие результаты:
Двухэтапный процесс фиксации транзакций XA хорошо виден на рисунке За более подробной информацией обратитесь к модулю XA Transactions базы данных MySQL.
На этом сегодня все. Надеюсь, эта статья поможет вам в учебе или работе. Если вы считаете, что статья хороша, вы можете подписаться на нее и поделиться ею с другими друзьями, чтобы больше людей могли узнать об этом. Спасибо.
Добро пожаловать в публичный аккаунт【Интернет плоский]. Обратите внимание на этого программиста, который борется за выживание в Интернете. Желаем вам и мне вместе добиться прогресса. Лучшее сегодня - это самые низкие требования завтра.