Distributed Transaction -Seata

SEAT


  • article Annuaire

1. Qu'est-ce que Seata?

Seata est une solution de transaction distribuée open source, offrant des performances et la facilité d'utilisation des services de transactions distribuées. Seata fournira aux utilisateurs un AT, TCC, SAGA et XA
mode de transaction, pour les utilisateurs de créer une solution unique pour distribuer. microarchitecture-services à haute performance et des solutions de transactions distribuées facile à utiliser

2. L'histoire du développement

Fourmis Service d'or:

  • XTS: Transaction Service Extended. Les fourmis équipe middleware robe d'or depuis 2007 pour développer un middleware de transaction distribuée, le middleware est largement utilisé dans les services de fourmis de costume d'or pour résoudre le problème de la cohérence des données entre les bases de données et services.

  • DTX: l'expansion des transactions Distribuée. Depuis 2013, XTS a des noms DTX publiés sur les fourmis nuage robe d'or.

Ali Baba:

  • TXC: équipe middleware Alibaba depuis 2014 pour démarrer le projet, afin de résoudre les problèmes causés par une architecture d'application de transaction distribuée à partir d'un seul service à micro changement causé

  • GTS: Global Transaction Services. Txc comme nouveau nom GTS Ali produits de middleware libérés en 2016

  • Fescar: A partir de 2019, nous avons commencé un projet open source basé Fescar TXC / gts afin de travailler en étroite collaboration avec la communauté à l'avenir

  • Seata: simple et architecture évolutive transaction autonome. Les fourmis ont rejoint la robe d'or Fescar, ce qui en fait une communauté de négociation distribué plus neutre et ouvert, alors que Fescar été renommé Seata

3. Micro-service distribué de transaction en question

Scène seule application conventionnelle - fournisseur d'électricité commercial. Son activité se compose de trois modules (inventaire, commandes et compte), ces trois modules à l'aide de la source de données locales respectives.

Au cours de l'entreprise se produit, la transaction locale pour assurer la cohérence des données.

l'architecture micro-services a changé. Les trois modules sont conçus mentionnés ci-dessus sur les trois sources différentes de trois services (Mode: base de données pour chaque service). Les affaires locales assure naturellement la cohérence des données pour chaque service.

4. Seata comment résoudre les transactions distribuées?

4.1 Principes de conception Seata pour résoudre la transaction distribuée:

4.2 Comment définir une transaction distribuée:

Les transactions distribuées sont des transactions mondiales par un groupe constitué de la branche d'affaires, cette opération de succursale est une transaction locale.

4.3 Seata Il y a trois éléments de base:

  • Coordinateur de transactions (TC): Direction de l'entretien et aux affaires mondiales de l'Etat, le lecteur ou la restauration mondiale commettras.
  • Transaction Manager (TM): la définition d'un champ de transaction globale: Démarrer la transaction globale, la transaction globale est validée ou annulée.
  • Resource Manager (RM): Affaires Direction de la gestion des ressources, communiquer avec TC pour enregistrer et signaler la branche de branche de transaction des affaires de l'Etat,

4.4 Gestion Seata des transactions distribuées du cycle de vie typique:

  • TM TC requis pour démarrer une nouvelle transaction globale. TC génère une transaction globale XID.

  • XID micro propagation en appelant des services de chaîne.

  • RM sera enregistrée en tant que XID de transaction locale à la branche appropriée de la transaction globale TC.

  • TM revendication TC correspondant transaction globale valider ou annuler le XID.

  • TC opération d'entraînement de toutes les branches dans le XID transaction globale respective de validation ou l'annulation de ramification.

5. SpringCloud intégré Seata

adresse de référence source GitHub

5.1 fonctionnement Seata

5.1.1 Seata Télécharger https://github.com/seata/seata/releases

5.1.2 profil Seata

la configuration du serveur Seata sont tous dans le dossier de fichier de configuration, dans ce dossier, il y a deux fichiers, nous devons être décrit en détail ci-dessous.

fichier par défaut du serveur Seata (papiers) aux journaux de transactions de magasin, exécutez les informations de transaction, nous pouvons être spécifiée par les paramètres de script sous forme de -m db, ne supporte actuellement que le fichier, db à la fois.

file.conf

Le fichier de configuration est utilisée pour le mode de stockage, des informations de transaction NIO informations de transmission transparent, le fichier correspondant mode par défaut du fichier de configuration registry.conf.

registry.conf

fichier de configuration Seata de base du serveur, vous pouvez configurer le service par le biais du dossier d'enregistrement, lisez le mode de configuration.

Inscrivez-vous en mode prend actuellement en charge le fichier, nacos, eurêka, Redis, ZK, consul, etcd3, canapé, etc., fichier par défaut, les informations d'enregistrement d'une manière correspondant à lecture de file.conf.

Reads la façon dont l'information de configuration dans un fichier de support, nacos, apollo, ZK, consul, etcd3 etc., fichier par défaut, lire le fichier de configuration correspondant à file.conf.

5.1.3 Exécuter Seata

environnement windows

seata-server.bat -p 8091 -m file

environnement Linux

sh seata-server.sh -p 8091 -m file                       #以前台运行方式运行seata

nohup sh seata-server.sh -p 8091 -h 127.0.0.1 -m file &> seata.log &            #以后台方运行式启动seata

-host numéro d'hôte -h spécifié de liaison, la valeur par défaut 0.0.0.0

-port -p Indique le numéro de port d'écoute, par défaut 8091

-storeMOde stockage -m journal (fichier, db), le fichier par défaut

5.2 Script d'initialisation sql

# Account
DROP SCHEMA IF EXISTS db_account;
CREATE SCHEMA db_account;
USE db_account;

CREATE TABLE `account_tbl`
(
    `id`      INT(11) NOT NULL AUTO_INCREMENT,
    `user_id` VARCHAR(255) DEFAULT NULL,
    `money`   INT(11)      DEFAULT 0,
    PRIMARY KEY (`id`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8;

INSERT INTO account_tbl (id, user_id, money)
VALUES (1, '1001', 10000);
INSERT INTO account_tbl (id, user_id, money)
VALUES (2, '1002', 10000);

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,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

# Order
DROP SCHEMA IF EXISTS db_order;
CREATE SCHEMA db_order;
USE db_order;

CREATE TABLE `order_tbl`
(
    `id`             INT(11) NOT NULL AUTO_INCREMENT,
    `user_id`        VARCHAR(255) DEFAULT NULL,
    `commodity_code` VARCHAR(255) DEFAULT NULL,
    `count`          INT(11)      DEFAULT '0',
    `money`          INT(11)      DEFAULT '0',
    PRIMARY KEY (`id`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8;

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,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

# Storage
DROP SCHEMA IF EXISTS db_storage;
CREATE SCHEMA db_storage;
USE db_storage;

CREATE TABLE `storage_tbl`
(
    `id`             INT(11) NOT NULL AUTO_INCREMENT,
    `commodity_code` VARCHAR(255) DEFAULT NULL,
    `count`          INT(11)      DEFAULT '0',
    PRIMARY KEY (`id`),
    UNIQUE KEY `commodity_code` (`commodity_code`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8;


INSERT INTO storage_tbl (id, commodity_code, count)
VALUES (1, '2001', 1000);

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,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

5.3 Structure du projet

  • ordre Service de commande servie
  • services marchands-services aux entreprises
  • commandes de service de commande de service
  • services d'entreposage de service de stockage

5.4 introduisirent dépendant Maven

<dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-all</artifactId>
    <version>1.1.0</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.0.4.RELEASE</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.11</version>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    <version>2.0.0.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
    <version>2.0.0.RELEASE</version>
</dependency>

5.5 fichiers de configuration

file.conf de configuration service.vgroup_mapping doit être cohérente et spring.application.name
dans org.springframework.cloud:spring-cloud-starter-alibaba-seata de classe org.springframework.cloud.alibaba.seata.GlobalTransactionAutoConfiguration, la valeur par défaut sera utilisé $ {} spring.application.name -fescar-service- groupe nom enregistré en tant que service à la Seata server, et si des incohérences de configuration file.conf, vous demandera aucun serveur disponible à l' erreur de connexion

Vous pouvez, mais doit être configuré spring.cloud.alibaba.seata.tx-groupe de service cohérent modifié la configuration et le suffixe file.conf

application.properties

spring.application.name=account-service
server.port=8083
spring.datasource.url=jdbc:mysql://localhost:3306/db_account?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.show-sql=true
spring.cloud.alibaba.seata.tx-service-group=my_group

file.conf

service {
  vgroupMapping.my_group = "account-service"
  account-service.grouplist = "127.0.0.1:8091"
  enableDegrade = false
  disableGlobalTransaction = false
}

5.6 démarrer le projet, illustré ci-dessous la preuve démarrage réussi:

5.7 Test:

Aucune erreur n'a été soumis avec succès:

curl http://127.0.0.1:8084/purchase/commit

Après l'achèvement de la base de données peut être vu dans account_tbl id est de l'argent 1 sera réduit 5, order_tbl ajoutera un enregistrement, id storage_tbl pour la réduction du champ de comptage 1 1

opération anormale est annulée:

curl http://127.0.0.1:8084/purchase/rollback

A ce service compte lève une exception, un retour en arrière se produit, les données contenues dans la base de données ne change pas avant l'achèvement d'une restauration réussie

6. SpringCloud intégré Seata + Nacos

adresse de référence source GitHub

6.1 fonctionnement Seata

6.1.1 modifier le fichier de configuration conf / registry.conf

Note: SERVERADDR pas 'http: //' préfixe

registry {
  # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
  type = "nacos"

  nacos {
    serverAddr = "114.55.34.44"
    namespace = ""
    cluster = "default"
  }
}
config {
  # file、nacos 、apollo、zk、consul、etcd3
  type = "nacos"
  nacos {
    serverAddr = "114.55.34.44"
    namespace = ""
    cluster = "default"
  }
}

6.1.2 modifier le fichier de configuration conf / nacos-config.txt (version Seata-service 1.1.0 seulement ou moins)

service.vgroup_mapping. et la en r - s e r v je c e - g r en la p = e F une en l t , en entre de {Votre service-gruop} = défaut, intermédiaire {votre service-gruop} nom pour la définition du groupe de services, application.properties service de fichiers de configuration dans le nom du groupe de services.

Il y a deux services démo, et sont pour service-service de stockage, de sorte que la configuration est la suivante:

service.vgroup_mapping.storage-service-group=default
service.vgroup_mapping.order-service-group=default

Initialisation Seata de configuration nacos:

cd conf
sh nacos-config.sh 114.55.34.44  #114.55.34.44为nacos的服务器地址

libération Seata-service 1.1.0 ajoute la configuration dans le manuel Nacos:

service.vgroupMapping.storage-service-group=default
service.vgroupMapping.order-service-group=default

Démarrez Seata service:

cd bin
sh seata-server.sh -p 8091 -m file

Après un écran de démarrage réussi comme suit:

6.1.3 initialisation script SQL

-- 创建 order库、业务表、undo_log表
create database seata_order;
use seata_order;

DROP TABLE IF EXISTS `order_tbl`;
CREATE TABLE `order_tbl` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` varchar(255) DEFAULT NULL,
  `commodity_code` varchar(255) DEFAULT NULL,
  `count` int(11) DEFAULT 0,
  `money` int(11) DEFAULT 0,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

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;


-- 创建 storage库、业务表、undo_log表
create database seata_storage;
use seata_storage;

DROP TABLE IF EXISTS `storage_tbl`;
CREATE TABLE `storage_tbl` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `commodity_code` varchar(255) DEFAULT NULL,
  `count` int(11) DEFAULT 0,
  PRIMARY KEY (`id`),
  UNIQUE KEY (`commodity_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

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;

-- 初始化库存模拟数据
INSERT INTO seata_storage.storage_tbl (id, commodity_code, count) VALUES (1, 'product-1', 9999999);
INSERT INTO seata_storage.storage_tbl (id, commodity_code, count) VALUES (2, 'product-2', 0);

6.1.4 introduisirent dépendante Maven

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

<!-- nacos -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    <version>0.2.1.RELEASE</version>
</dependency>

<!-- seata-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-seata</artifactId>
    <version>2.1.0.RELEASE</version>
</dependency>
<dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-all</artifactId>
    <version>1.1.0</version>
</dependency>

<!-- mysql -->
<dependency>
    <groupId>com.work</groupId>
    <artifactId>base-framework-mysql-support</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

6.1.5 Profil registy.conf

registry {
  # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
  type = "nacos"

  nacos {
    serverAddr = "114.55.34.44"
    namespace = ""
    cluster = "default"
  }
}
config {
  # file、nacos 、apollo、zk、consul、etcd3
  type = "nacos"
  nacos {
    serverAddr = "114.55.34.44"
    namespace = ""
    cluster = "default"
  }
}

6.1.6 Profil application.properties

Service de commande

spring.application.name=order-service
server.port=9091

# Nacos 注册中心地址
spring.cloud.nacos.discovery.server-addr = 114.55.34.44:8848

# seata 服务分组,要与服务端nacos-config.txt中service.vgroup_mapping的后缀对应
spring.cloud.alibaba.seata.tx-service-group=order-service-group
logging.level.io.seata = debug

# 数据源配置
spring.datasource.druid.url=jdbc:mysql://114.55.34.44:3306/seata_order?allowMultiQueries=true
spring.datasource.druid.driverClassName=com.mysql.jdbc.Driver
spring.datasource.druid.username=root
spring.datasource.druid.password=root

stockage service

spring.application.name=storage-service
server.port=9092

# Nacos 注册中心地址
spring.cloud.nacos.discovery.server-addr = 114.55.34.44:8848

# seata 服务分组,要与服务端nacos-config.txt中service.vgroup_mapping的后缀对应
spring.cloud.alibaba.seata.tx-service-group=storage-service-group
logging.level.io.seata = debug

# 数据源配置
spring.datasource.druid.url=jdbc:mysql://114.55.34.44:3306/seata_storage?allowMultiQueries=true
spring.datasource.druid.driverClassName=com.mysql.jdbc.Driver
spring.datasource.druid.username=root
spring.datasource.druid.password=root

6.1.7 Articles de démarrage

6.1.8 Test

transaction distribuée est réussie, simulent des commandes normales, boucle d'inventaire

curl localhost:9091/order/placeOrder/commit

transaction distribuée échoue, le succès unique analogique, inventaire boucle de défaillance, et le dos finalement roulé en même temps

curl localhost:9091/order/placeOrder/rollback

Plus de centres d'enregistrement et cadre intégré, la documentation de référence

Publié 11 articles originaux · louange gagné 2 · Vues 431

Je suppose que tu aimes

Origine blog.csdn.net/qq_41112063/article/details/105314104
conseillé
Classement