написать впереди
Seata — это решение Alibaba для распределенных транзакций с открытым исходным кодом, предназначенное для предоставления высокопроизводительных и простых в использовании сервисов распределенных транзакций. Seata предоставит пользователям режимы транзакций AT, TCC, SAGA и XA, создав универсальное распределенное решение для пользователей.Эта статья поможет вам создать решение для распределенных транзакций на основе Seata от начала до конца, а соответствующий контент будет более подробным.
Заодно рисуем карту с XMindЗапишите учебные заметки Spring Cloud Alibaba(Исходный файл содержит подробные примечания и справочные материалы для некоторых узлов. Поскольку он слишком велик, он не показывает их все.Добро пожаловать, чтобы обратить внимание на мою официальную учетную запись: Примечания к архитектуре Afeng Отправьте [карту] в фоновом режиме, чтобы получить ссылку для скачивания,Он был улучшен и обновлен):
Основы распределенных транзакций
дела
Транзакция относится к операционной единице, в которой все операции в этой операционной единице в конечном итоге сохраняют согласованное поведение, либо все операции завершаются успешно, либо все операции отменяются. Проще говоря, транзакции обеспечивают механизм «ничего не делать или делать все целиком».
местные дела
Локальные вещи фактически можно рассматривать как механизм транзакций, предоставляемый базой данных. Когда дело доходит до транзакций базы данных, мы должны сказать, что у транзакций базы данных есть четыре основные характеристики:
-
A: Атомарность, все операции в транзакции либо завершены, либо не завершены
-
C: Согласованность, база данных должна быть в согласованном состоянии до и после выполнения транзакции.
-
I: Изоляция, в параллельной среде, когда разные транзакции обрабатывают одни и те же данные одновременно, транзакции не влияют друг на друга.
-
D: Долговечность, что означает, что до тех пор, пока транзакция завершается успешно, обновления, которые она вносит в базу данных, должны сохраняться постоянно.
Когда выполняется транзакция базы данных, все операции, связанные с транзакцией, включаются в неделимую исполнительную единицу. Все операции в исполнительной единице либо завершаются успешно, либо терпят неудачу. Если какая-либо из операций завершается сбоем, это вызывает всю операцию. сделки
Распределенная транзакция
Распределенная транзакция означает, что участники транзакции, серверы поддержки транзакций, серверы ресурсов и менеджеры транзакций расположены на разных узлах разных распределенных систем.
Проще говоря, большая операция состоит из разных маленьких операций.Эти маленькие операции распределены по разным серверам и принадлежат разным приложениям.Распределенные транзакции должны гарантировать, что все эти маленькие операции завершатся успешно или все потерпят неудачу.
По сути, распределенные транзакции предназначены для обеспечения согласованности данных в разных базах данных.
Сценарии для распределенных транзакций
Монолитная система с доступом к нескольким базам данных
Служба должна вызывать несколько экземпляров базы данных для завершения операций добавления, удаления и изменения данных.
Несколько микросервисов, обращающихся к одной и той же базе данных
Несколько служб должны вызывать экземпляр базы данных для завершения операций добавления, удаления и изменения данных.
Несколько микросервисов, обращающихся к нескольким базам данных
Несколько служб должны вызывать экземпляр базы данных для завершения операций добавления, удаления и изменения данных.
Решения для распределенных транзакций
глобальная транзакция
Глобальные транзакции реализованы на основе модели DTP. DTP — это модель распределенных транзакций, предложенная организацией X/Open — эталонная модель обработки распределенных транзакций X/Open. В нем указано, что для реализации распределенных транзакций требуются три роли:
-
AP: система прикладных приложений (микросервис)
-
TM: Менеджер транзакций Менеджер транзакций (глобальное управление транзакциями)
-
RM: Менеджер ресурсов Менеджер ресурсов (база данных)
Вся сделка делится на два этапа:
-
Этап 1: на этапе голосования все участники предварительно фиксируют транзакцию и отправляют координатору отзывы о том, успешна она или нет.
-
Фаза 2: на этапе выполнения координатор уведомляет всех участников в соответствии с отзывами всех участников и одновременно выполняет фиксацию или откат.
преимущество
- Повышенная вероятность согласованности данных и снижение затрат на внедрение
недостаток
-
Единая точка выдачи: координатор транзакций не работает
-
Синхронная блокировка: задержка времени отправки и увеличение времени блокировки ресурса.
-
Несогласованность данных: на втором этапе отправки результат фиксации все еще неизвестен, что может привести к несогласованности данных.
надежный сервис обмена сообщениями
Решение, основанное на надежной службе сообщений, заключается в обеспечении согласованности операций с данными вышестоящего и нижестоящего приложений с помощью промежуточного программного обеспечения сообщений. Предположим, что есть две системы, A и B, которые могут обрабатывать задачи A и B соответственно. На данный момент есть бизнес-процесс, и задача A и задача B должны быть обработаны в одной и той же транзакции. Эта распределенная транзакция может быть реализована с использованием промежуточного программного обеспечения сообщений.
Шаг 1. Сообщение доставляется системой А промежуточному программному обеспечению.
-
Прежде чем система A обработает задачу A, она сначала отправляет сообщение промежуточному программному обеспечению сообщений.
-
ПО промежуточного слоя сообщений сохраняет сообщение после его получения, но не доставляет его. После успешного сохранения ответьте ответом подтверждения на A
-
После того, как система A получит ответ с подтверждением, она может начать обработку задачи A.
-
После обработки задачи A в промежуточное программное обеспечение сообщений отправляется запрос Commit или Rollback. После отправки запроса для системы А обработка транзакции заканчивается
-
Если промежуточное программное обеспечение сообщений получает Commit, оно доставляет сообщение системе B; если оно получает Rollback, оно напрямую отбрасывает сообщение. Однако, если промежуточное программное обеспечение сообщений не может получить команды Commit и Rollback, оно должно полагаться на «механизм запроса тайм-аута».
Механизм запроса тайм-аута
В дополнение к реализации обычного бизнес-процесса, система А также должна предоставить интерфейс для запроса транзакций для вызова промежуточного программного обеспечения сообщений. Когда промежуточное программное обеспечение сообщений получает опубликованное сообщение, оно начинает отсчет времени.Если оно не получает инструкции подтверждения по истечении тайм-аута, оно будет активно вызывать интерфейс запроса транзакции, предоставляемый системой А, чтобы узнать о текущем состоянии системы. Интерфейс будет возвращать три типа результатов, и промежуточное ПО будет реагировать по-разному в зависимости от трех типов результатов:
Отправить: доставить сообщение в систему B.
Откат: сразу отбросить сообщение
Обработка: продолжайте ждать
Шаг 2: Сообщение доставляется в систему B промежуточным программным обеспечением.
После того, как промежуточное программное обеспечение сообщений доставляет сообщение нижестоящей системе, оно переходит в состояние ожидания блокировки, нижестоящая система немедленно обрабатывает задачу и возвращает ответ промежуточному программному обеспечению сообщений после обработки задачи.
-
Если промежуточное программное обеспечение сообщений получает ответ подтверждения, оно считает транзакцию завершенной.
-
Если промежуточное программное обеспечение сообщений ожидает истечения времени ожидания подтверждающего ответа, оно будет повторно доставлено до тех пор, пока нижестоящий потребитель не вернет ответ об успешном потреблении.
Как правило, промежуточное программное обеспечение сообщений может устанавливать количество попыток и временной интервал для повторной отправки сообщения.Если сообщение не может быть успешно доставлено в конце, требуется ручное вмешательство. Причина, по которой здесь используется ручное вмешательство вместо отката системы А, в основном связана со сложностью всей конструкции системы.
Для распределенных транзакций, основанных на надежных службах сообщений, первая половина использует асинхронность с упором на производительность, а вторая половина использует синхронизацию с упором на затраты на разработку.
уведомление о лучших усилиях
Уведомление о максимальных усилиях, также известное как периодическая корректура, представляет собой дальнейшую оптимизацию второго решения. Он вводит локальную таблицу сообщений для записи сообщений об ошибках, а затем добавляет периодическую проверку ошибочных сообщений, чтобы дополнительно гарантировать, что сообщения будут использоваться нижестоящими системами.
Шаг 1. Сообщение доставляется системой А промежуточному программному обеспечению.
-
В той же транзакции, которая обрабатывает бизнес, напишите запись в локальную таблицу сообщений
-
Подготовьте выделенного отправителя сообщений для непрерывной отправки сообщений из локальной таблицы сообщений промежуточному программному обеспечению сообщений и повторите попытку, если отправка не удалась.
Шаг 2: Сообщение доставляется в систему B промежуточным программным обеспечением.
-
После получения сообщения промежуточное программное обеспечение сообщений отвечает за синхронную доставку сообщения в соответствующую нижестоящую систему и запуск выполнения задачи нижестоящей системы.
-
Когда нижестоящая система обрабатывает успешно, она отправляет подтверждающий ответ промежуточному программному обеспечению сообщений, и промежуточное программное обеспечение сообщений может удалить сообщение, тем самым завершив транзакцию.
-
Для сообщений, которые не удалось доставить, используйте механизм повторной попытки, а для тех, которые не удалось повторить, запишите в таблицу сообщений об ошибках.
-
Промежуточное программное обеспечение сообщений должно предоставлять интерфейс запросов для сообщений об ошибках, а нижестоящая система будет периодически запрашивать сообщения об ошибках и использовать их.
Преимущества и недостатки этого способа:
-
преимущество:Очень классическая реализация, которая обеспечивает окончательную согласованность.
-
недостаток:Таблица сообщений будет привязана к бизнес-системе, и если готового решения не будет, придется выполнять много рутинной работы.
дела ТСС
TCC — это Try Confifirm Cancel, компенсирующая распределенная транзакция. В TCC есть три шага для реализации распределенных транзакций:
-
Пытаться:Попробуйте выполнить бизнес: этот процесс не выполняет бизнес, а просто завершает проверку согласованности всего бизнеса и резервирует все ресурсы, необходимые для выполнения.
-
Подтвердить:Подтвердите выполнение бизнес-операции: подтвердите выполнение бизнес-операции, не выполняйте никаких бизнес-проверок и используйте только бизнес-ресурсы, зарезервированные на этапе пробной версии. Как правило, использование TCC предполагает, что фаза подтверждения не содержит ошибок. То есть: до тех пор, пока попытка успешна, подтверждение будет успешным. Если на этапе подтверждения возникает ошибка, необходимо внедрить механизм повторных попыток или ручную обработку.
-
Отмена:Отмените услугу, которую нужно выполнить: отмените бизнес-ресурс, зарезервированный на этапе TRY. Обычно TCC используется для достижения успеха. Если фаза отмены действительно неверна, вам нужно ввести механизм повторных попыток или ручное лечение.
Разница между двухфазной фиксацией TCC и двухфазной фиксацией XA заключается в следующем:
-
XA — это распределенная транзакция на уровне ресурсов со строгой согласованностью.Во время всего процесса двухэтапной фиксации блокировка ресурса всегда будет удерживаться.
-
TCC — это распределенная транзакция на бизнес-уровне с возможной согласованностью, которая не всегда удерживает блокировки ресурсов.
Преимущества и недостатки транзакций TCC:
-
преимущество: второй этап представления уровня базы данных реализован путем обращения к уровню приложений, что позволяет избежать проблемы низкой производительности 2PC на уровне базы данных.
-
недостаток: Операционные функции «Попробовать», «Подтвердить» и «Отменить TCC» должны быть предоставлены бизнесом, а стоимость разработки высока.
Введение Сеата
В январе 2019 года команда промежуточного программного обеспечения Alibaba запустила проект с открытым исходным кодом.Fescar(Fast & EaSy Commit AndRollback), его видение состоит в том, чтобы сделать использование распределенных транзакций таким же простым и эффективным, как и использование локальных транзакций, и постепенно решить все проблемы, с которыми сталкиваются разработчики в распределенных транзакциях. позже переименованSeata, что означает: простая расширяемая архитектура автономных транзакций, представляет собой набор решений для распределенных транзакций.
Целью разработки Seata является ненавязчивость бизнеса, поэтому она начинается с решения 2PC, которое не мешает бизнесу и развивается на основе традиционного 2PC. Он понимает распределенную транзакцию как глобальную транзакцию, содержащую несколько ветвящихся транзакций. Ответственность за глобальную транзакцию заключается в координации транзакций филиалов под ее юрисдикцией для достижения консенсуса либо для успешной совместной фиксации, либо для отката в случае сбоя вместе. Кроме того, обычно сама транзакция филиала является локальной транзакцией реляционной базы данных.
Seata в основном состоит из трех важных компонентов:
-
TC: Координатор транзакций Координатор транзакций управляет состоянием транзакций глобальных ветвей и используется для фиксации и отката глобальных транзакций.
-
TM: менеджер транзакций Transaction Manager, используемый для открытия, подтверждения или отката глобальных транзакций.
-
RM: Диспетчер ресурсов Диспетчер ресурсов, используемый для управления ресурсами транзакций ветвей, регистрации транзакций ветвей с помощью TC, отчетов о состоянии транзакций ветвей и приема команд TC для фиксации или отката транзакций ветвей.
Поток выполнения Seata выглядит следующим образом:
-
TM службы A обращается к TC, чтобы открыть глобальную транзакцию, и TC создаст глобальную транзакцию и вернет уникальный XID.
-
RM службы A регистрирует транзакцию филиала в TC и включает ее в юрисдикцию глобальной транзакции, соответствующей XID.
-
Служба выполняет транзакции ветвей и выполняет операции с базой данных.
-
Служба A начинает удаленно вызывать службу B, и в это время XID будет распространяться по цепочке вызовов микрослужбы.
-
RM службы B регистрирует транзакцию филиала в TC и включает ее в юрисдикцию глобальной транзакции, соответствующей XID.
-
Служба B выполняет транзакции ветвей и работает с базой данных.
-
После обработки цепочки вызовов глобальной транзакции TM инициирует отправку или откат глобальной транзакции в TC в зависимости от того, есть ли аномалия или нет.
-
ТК координирует все дела филиала, находящиеся в его ведении, и принимает решение об откате
Разница Seata в 2PC и традиционных 2PC:
-
С точки зрения архитектуры, RM традиционного 2PC-решения фактически находится на уровне базы данных, RM — это, по сути, сама база данных, которая реализована через протокол XA, в то время как RM Seata развертывается в виде jar-пакета. в качестве промежуточного слоя на стороне приложения.
-
С точки зрения двухэтапной фиксации, в традиционном 2PC, независимо от того, является ли разрешение второй фазы фиксацией или откатом, блокировки транзакционных ресурсов должны удерживаться до завершения фазы 2, а затем освобождаться. Подход Seata состоит в том, чтобы отправить локальную транзакцию в Фазе 1, что экономит время, которое Фаза 2 удерживает блокировку, и повышает общую эффективность.
Seata реализует распределенный контроль транзакций
В этом примере реализованы распределенные транзакции через промежуточное ПО Seata, имитирующие процесс размещения заказов и вычета запасов в электронной коммерции.
Мы выполняем операцию заказа через микросервис заказа, а затем микросервис заказа вызывает микросервис товара, чтобы вычесть запасы.
базовый код случая
Изменить микросервис заказа
controller
@RestController
@Slf4j
public class OrderController5 {
@Autowired
private OrderServiceImpl5 orderService;
//下单
@RequestMapping("/order/prod/{pid}")
public Order order(@PathVariable("pid") Integer pid) {
log.info("接收到{}号商品的下单请求,接下来调用商品微服务查询此商品信息", pid);
return orderService.createOrder(pid);
}
}
OrderService
@Service
@Slf4j
public class OrderServiceImpl5{
@Autowired
private OrderDao orderDao;
@Autowired
private ProductService productService;
@Autowired
private RocketMQTemplate rocketMQTemplate;
@GlobalTransactional
public Order createOrder(Integer pid) {
//1 调用商品微服务,查询商品信息
Product product = productService.findByPid(pid);
log.info("查询到{}号商品的信息,内容是:{}", pid, JSON.toJSONString(product));
//2 下单(创建订单)
Order order = new Order();
order.setUid(1);
order.setUsername("测试用户");
order.setPid(pid);
order.setPname(product.getPname());
order.setPprice(product.getPprice());
order.setNumber(1);
orderDao.save(order);
log.info("创建订单成功,订单信息为{}", JSON.toJSONString(order));
//3 扣库存
productService.reduceInventory(pid, order.getNumber());
//4 向mq中投递一个下单成功的消息
rocketMQTemplate.convertAndSend("order-topic", order);
return order;
}
}
ProductService
@FeignClient(value = "service-product")
public interface ProductService {
//减库存
@RequestMapping("/product/reduceInventory")
void reduceInventory(@RequestParam("pid") Integer pid, @RequestParam("num")
int num);
}
Изменить микросервис продукта
controller
//减少库存
@RequestMapping("/product/reduceInventory")
public void reduceInventory(Integer pid, int num) {
productService.reduceInventory(pid, num);
}
service
@Override
public void reduceInventory(Integer pid, int num) {
Product product = productDao.findById(pid).get();
product.setStock(product.getStock() - num);
//减库存
productDao.save(product);
}
имитация исключений
Смоделируйте исключение в коде ProductServiceImpl, а затем вызовите интерфейс заказа.
@Override
public void reduceInventory(Integer pid, Integer number) {
Product product = productDao.findById(pid).get();
if (product.getStock() < number) {
throw new RuntimeException("库存不足");
}
int i = 1 / 0;
product.setStock(product.getStock() - number);
productDao.save(product);
}
Старт Сеата
скачать Seata
ссылка на скачивание:GitHub.com/цвет ах/цвет ах…
Изменить файл конфигурации
Разархивируйте загруженный сжатый пакет, войдите в каталог conf и настройте следующие файлы конфигурации:
registry.conf
registry {
type = "nacos"
nacos {
serverAddr = "localhost"
namespace = "public"
cluster = "default"
}
}
config {
type = "nacos"
nacos {
serverAddr = "localhost"
namespace = "public"
cluster = "default"
}
}
nacos-confifig.txt
service.vgroup_mapping.service-product=default
service.vgroup_mapping.service-order=default
Синтаксис здесь:service.vgroup_mapping.${your-service-gruop}=default
,Середина${your-service-gruop}
Название сервисной группы определили для себя, здесь нам нужно настроить его в конфигурационном файле программы
Инициализируйте конфигурацию Seata в nacos
\# 初始化seata 的nacos配置
\# 注意: 这里要保证nacos是已经正常运行的
cd conf
nacos-config.sh 127.0.0.1
После успешного выполнения вы можете открыть консоль Nacos.В списке конфигурации вы можете увидеть, что многие группы инициализированы как SEATA_GROUP.
запустить службу сиденья
cd bin
seata-server.bat -p 9000 -m file
После запуска вы можете увидеть службу с именем serverAddr в списке служб Nacos.
Контроль транзакций с Seata
Инициализировать таблицу данных
Добавьте в нашу базу данных таблицу undo_log, которую Seata использует для записи журналов транзакций.
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;
добавить конфигурацию
Выполните следующие настройки в микросервисах, требующих распределенного управления:
добавить зависимости
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
DataSourceProxyConfifig
Seata реализует ветвление транзакций через прокси-источники данных, поэтому необходимо настроить bean-компонент io.seata.rm.datasource.DataSourceProxy, а он является источником данных по умолчанию @Primary, иначе транзакция не будет откатываться и распределять транзакции не может быть реализован
@Configuration
public class DataSourceProxyConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DruidDataSource druidDataSource() {
return new DruidDataSource();
}
@Primary
@Bean
public DataSourceProxy dataSource(DruidDataSource druidDataSource) {
return new DataSourceProxy(druidDataSource);
}
}
registry.conf
Добавьте файл конфигурации SeataRegistry.conf в ресурсы
registry {
type = "nacos"
nacos {
serverAddr = "localhost"
namespace = "public"
cluster = "default"
}
}
config {
type = "nacos"
nacos {
serverAddr = "localhost"
namespace = "public"
cluster = "default"
}
}
bootstrap.yaml
spring:
application:
name: service-product
cloud:
nacos:
config:
server-addr: localhost:8848 # nacos的服务端地址
namespace: public
group: SEATA_GROUP
alibaba:
seata:
tx-service-group: ${
spring.application.name
}
Запуск глобальных транзакций в микросервисе заказа
@GlobalTransactional//全局事务控制
public Order createOrder(Integer pid) {}
контрольная работа
заказать тест еще раз
Анализ рабочего процесса Seata
Ключевые моменты:
-
Каждый RM использует DataSourceProxy для подключения к базе данных, и его целью является использование ConnectionProxy. Цель использования источника данных и прокси-сервера подключения данных — поместить undo_log и бизнес-данные в локальную отправку транзакции на первом этапе, чтобы сохранить как пока есть бизнес-операция Есть undo_log.
-
На первом этапе undo_log хранит значения до и после модификации данных для подготовки к откату транзакции, поэтому транзакция ветвления была зафиксирована после завершения первого этапа, и ресурсы блокировки освобождены.
-
ТМ запускает глобальную транзакцию, помещает глобальный идентификатор транзакции XID в контекст транзакции, а также передает XID в транзакцию нижестоящей ветви через фиктивный вызов.Каждая транзакция ветви связывает свой идентификатор транзакции ветви ID с XID.
-
На втором этапе отправки глобальной транзакции TC уведомит каждого участника филиала о необходимости отправки транзакции филиала.Транзакция филиала была отправлена на первом этапе.Здесь каждому участнику нужно только удалить undo_log, и это может быть выполнено асинхронно. второй этап Можно сделать в ближайшее время.
-
На втором этапе глобального отката транзакции TC уведомит каждого участника ветки о необходимости отката транзакции ветки, найдет соответствующий журнал отката через XID и ID ветки, сгенерирует обратный SQL через журнал отката и выполнит его для завершения отката транзакции ветки. вернуться в предыдущее состояние и повторить операцию отката, если откат не удался
Прочитав три вещи ❤️
Если вы считаете, что этот контент очень полезен для вас, я хотел бы пригласить вас сделать мне три небольших одолжения:
- Лайки, репосты и ваши "лайки и комментарии" - движущая сила моего творчества.
- Обратите внимание на публичный аккаунт«Архитектурные заметки Фэна», делитесь оригинальными знаниями время от времени.
- В то же время вы можете рассчитывать на последующие статьи🚀
- Подпишитесь и ответьте [666] Отсканируйте код, чтобы получить пакет расширенного обучения архитектуре