Alibaba 分散トランザクション フレームワーク Seata 統合の詳細

大家好,我是曹尼玛
ここに画像の説明を挿入します
从大学毕业5年,一直努力学习,努力工作,追求新技术,不保守。
ここに画像の説明を挿入します
上个月我来到一家新公司上班,月薪20K,这家公司老板人很好,对员工很关爱,公司氛围不错,同事们也努力把公司项目搞搞好。除了那个混日子的10年开发经验的老王(老板小舅子)
ここに画像の説明を挿入します
由于老板对客户比较负责,业界口碑好,公司的项目越做越大,单子也越来越多,但是很多客户项目要求分布式微服务,因为大部分是金融外贸项目,搞了微服务后,偶尔出现分布式事务不一致性问题,客户很是反感,前段时间,公司用TCC试水,发现这个方案代码侵入性太强,维护也不方便,人工投入太大,也容易编码出错。
ここに画像の説明を挿入します
后来用基于RocketMQ消息队列实现可靠消息最终一致性方案代替,能实现要求,比TCC好维护点,但是实现起来,终究得依赖消息中间件,而且逻辑也有点繁琐,公司项目涉及到得分布式事务模块还是很多的,搞得天罗地网似的。
ここに画像の説明を挿入します
公司急于寻求一种简单快捷高效的低代码侵入式的分布式事务解决方案。
ここに画像の説明を挿入します
作为新技术控,我一直关注新技术,最近2年,阿里分布式事务解决方案Seata很火,人气很足!
ここに画像の説明を挿入します
也深入研究过,现在最新版本1.4.2,基本成熟了,可以商用!作为Spring Cloud Alibaba服务组件,很好集成到项目里,而且我都深入测试过!
So I mustered up the courage and walked directly to my boss's office and asked him to try Seata;
ここに画像の説明を挿入します
My boss is not a conservative person and is willing to try !他说他先研究下Seata。
ここに画像の説明を挿入します
第二天,老板叫我进办公室,直接说“公司的438项目,有一个sb模块涉及分布式事务,你用seata搞下”。我连忙说”OK,没问题,保证完成任务“!
ここに画像の説明を挿入します
由于我对seata比较熟悉,MD笔记整理得井井有条。所以一顿猛操,seata-server配置下,启动,微服务项目applicaton.yml配置下,@GlobalTransactional加上,测试下,没问题,一上午就撸完了,跟老板说”可以让测试部的小姐姐测试下了“。
ここに画像の説明を挿入します
老板惊呆了,这么快就搞完了?半信半疑
ここに画像の説明を挿入します
下午测试部的小姐姐们仔细功能测试,压测,没毛病!偶尔服务调用超时也是自动回滚事务,所以不影响业务,界面有友好用户提示”系统繁忙,请稍后重试“!
ここに画像の説明を挿入します
老板听到测试部的汇报后,直接让版本更新放到线上让客户使用!
用了一个多月,根据客户反馈,以及日志系统查看,这次seata解决方案非常OK!
ここに画像の説明を挿入します
老板让漂亮的小秘把我叫到办公室,然后塞给我一沓厚厚的信封,跟我说 ”曹大哥,明天开始,那个混饭吃胡日子不思进取的10年经验的老王就要滚蛋了,以后技术总监的位置就是你的了,薪资是40K,15薪资+项目奖金+年终奖“,”另外还有特殊福利“,顺便喵看了下旁边芳龄18的小敏秘书!
ここに画像の説明を挿入します
由于我过于激动,那天说话老是合不拢嘴!
ここに画像の説明を挿入します
3年以后,我成为了公司技术一把手,年入百万;
第4年,我当爸爸了,选了个风和日丽的日子,开着保时捷Panamera,带着满月的儿子和小敏一起去拍满月照!
ここに画像の説明を挿入します
ここに画像の説明を挿入します
阿里Seata作为一个优秀得分布式事务解决方案,让穷屌丝的我逆袭了,我决定公开我的seata笔记,顺便还录制了一套Seata视频教程,希望对大家有帮助!

1 アリババの分散トランザクションフレームワーク Seata の紹介

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。

中文官方站点:https://seata.io/zh-cn/

seata github开源地址:https://github.com/seata

2 分散トランザクションの概要

2.1 地域情勢

コンピュータ システムでは、トランザクションは主にリレーショナル データベースによって制御されます。これは、データベース自体のトランザクション特性を使用することによって実現されるため、データベース トランザクションと呼ばれます。アプリケーションは主にリレーショナル データベースに依存してトランザクションを制御するため、データベースは通常、リレーショナル データベースと組み合わせて使用​​されます。同じサーバーにあるため、リレーショナル データベースに基づくトランザクションはローカル トランザクションとも呼ばれます。

データベース トランザクションの 4 つの主な特徴: ACID

A (アトミック): アトミック性。トランザクションを構成するすべての操作が完了するか、まったく実行されず、部分的に成功したり部分的に失敗したりする可能性はありません。

C (一貫性): 一貫性。データベースの一貫性制約は、トランザクションの実行前後に破棄されません。例: Zhang San が Li Si に 100 元を送金し、送金前後のデータは正しいです。これを一貫性と呼びます。Zhang San が 100 元を送金しても、Li Si の口座が 100 元増えなかった場合、データエラーです。整合性が取れません。

I (分離): 分離。データベース内のトランザクションは通常、同時実行されます。分離とは、2 つの同時トランザクションの実行が互いに干渉しないことを意味します。1 つのトランザクションは実行できません。実行中の他のトランザクションの中間状態。トランザクション分離レベルを構成すると、ダーティ リードや繰り返し読み取りを回避できます。

D (耐久性): 耐久性。トランザクションの完了後、トランザクションによって行われたデータへの変更はデータベースに保持され、ロールバックされません。

データベース トランザクションが実装されると、トランザクションのすべての操作が分割不可能な実行ユニットに組み込まれます。この実行ユニットのすべての操作は成功するか失敗します。操作のいずれか 1 つが実行に失敗すると、全体の操作が失敗します。トランザクションは失敗します。ロールバックします。

2.2 分散トランザクション

インターネットの急速な発展に伴い、ソフトウェア システムは元の単一アプリケーションから分散アプリケーションに変わりました。

分散システムでは、アプリケーション システムが独立して展開できる複数のサービスに分割されます。そのため、トランザクション操作を完了するには、サービス間のリモート コラボレーションが必要です。この分散システム環境は、さまざまなサービスで構成されています。トランザクションは、複数のリモート コラボレーションを通じて完了します。このネットワークは分散トランザクションと呼ばれ、ユーザー登録やボーナスポイントトランザクション、注文在庫削減トランザクションの作成、銀行振込トランザクションなどです。分散トランザクション。

3 SpringCloud Alibaba 分散基本ケースの構築

単純な注文ビジネスをシミュレートします。クライアントが REST 外部サービスを呼び出し、REST サービスが注文サービスを呼び出して注文を作成し、アカウント サービスを呼び出して口座引き落とし操作を実現し、最終的に注文ビジネスを完了します。

2.1 ケースアーキテクチャ設計

すべてのサービスは、偽りのリモート呼び出しを容易にするために nacos に登録されています。注文サービスとアカウント サービスにはそれぞれ独立したデータベースがあります。アーキテクチャ設計は次のとおりです。
ここに画像の説明を挿入します

プロジェクト全体の構造は次のとおりです。
ここに画像の説明を挿入します

seatatestこれは親プロジェクトであり、主に依存関係の管理、依存関係のバージョン管理を行い、すべてのサブモジュール プロジェクトを管理します。

seata-commonサブプロジェクトは主に、他のサブプロジェクトが必要とするパブリック依存関係、およびパブリック エンティティ、ツール クラス、構成クラスの統合カプセル化を導入します。

seata-orderサブプロジェクトは主に注文サービスを提供し、注文を生成します。

seata-accountサブプロジェクトは主に口座サービスを提供し、注文に基づいてお金を引き落とします。

seata-webサブプロジェクトは主にクライアントの注文リクエストを処理し、リモートで注文を呼び出すふりをし、アカウント サービス インターフェイスを処理し、最終的に注文処理を完了します。

2.2 データベース設計

db_order (注文データベース)、db_account (アカウント データベース)、 という 2 つの新しいデータベースを作成します。

db_orderデータベースに新しいテーブルを作成するt_orderテーブルの順序:

CREATE TABLE `t_order` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `orderNo` varchar(100) DEFAULT NULL,
  `userId` int(11) DEFAULT NULL,
  `count` int(11) DEFAULT NULL,
  `amount` int(11) DEFAULT NULL,
  `remark` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8

db_accountデータベースに新しいテーブルを作成するt_accountユーザー アカウント テーブル:

CREATE TABLE `t_account` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `userId` int(11) DEFAULT NULL,
  `balance` int(11) DEFAULT NULL,
  `remark` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8

データを挿入します:

insert into `t_account` (`id`, `userId`, `balance`, `remark`) values('1','1','2000','jack的账户');
insert into `t_account` (`id`, `userId`, `balance`, `remark`) values('2','2','1000','marry的账户');

2.3 最も重要な親プロジェクトの構築

Seatatest は親プロジェクトで、主に依存関係の管理、依存関係のバージョン管理を行い、すべてのサブモジュール プロジェクトを管理します。

そのpackagingタイプはであることに注意してください。pom

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.java1234</groupId>
    <artifactId>seatatest</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>seata-common</module>
        <module>seata-order</module>
        <module>seata-account</module>
        <module>seata-web</module>
    </modules>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <druid.version>1.1.10</druid.version>
        <spring-cloud.version>Hoxton.SR8</spring-cloud.version>
        <springboot.version>2.3.2.RELEASE</springboot.version>
        <springcloudalibaba.version>2.2.4.RELEASE</springcloudalibaba.version>
        <fastjson.version>1.2.35</fastjson.version>
        <commons-lang3.version>3.6</commons-lang3.version>
        <seata-common.version>1.0-SNAPSHOT</seata-common.version>
        <mybatis.version>2.1.0</mybatis.version>
    </properties>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${springboot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${springcloudalibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- 连接池 -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>${druid.version}</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId><artifactId>fastjson</artifactId> <version>${fastjson.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
                <version>${commons-lang3.version}</version>
            </dependency>
            <dependency>
                <groupId>com.java1234</groupId>
                <artifactId>seata-common</artifactId>
                <version>${seata-common.version}</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

2.4 シータ共通サブプロジェクト建設

seata-commonサブプロジェクトは主に、他のサブプロジェクトが必要とするパブリック依存関係、およびパブリック エンティティ、ツール クラス、構成クラスの統合カプセル化を導入します。

プロジェクトの構造:
ここに画像の説明を挿入します

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>seatatest</artifactId>
        <groupId>com.java1234</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>seata-common<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependencies</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.boot<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-boot-starter-web<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.boot<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-boot-starter-test<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>scope</span><span class="token punctuation">&gt;</span></span>test<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>scope</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>

    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>com.alibaba.cloud<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-cloud-starter-alibaba-nacos-discovery<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>com.alibaba.cloud<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-cloud-starter-alibaba-nacos-config<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.boot<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-boot-devtools<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>scope</span><span class="token punctuation">&gt;</span></span>runtime<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>scope</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>optional</span><span class="token punctuation">&gt;</span></span>true<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>optional</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>mysql<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>mysql-connector-java<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>scope</span><span class="token punctuation">&gt;</span></span>runtime<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>scope</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.projectlombok<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>lombok<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.boot<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-boot-starter-test<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>scope</span><span class="token punctuation">&gt;</span></span>test<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>scope</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.mybatis.spring.boot<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>mybatis-spring-boot-starter<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>com.alibaba<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>druid<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token comment">&lt;!-- spring boot redis 缓存引入 --&gt;</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.boot<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-boot-starter-data-redis<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token comment">&lt;!-- lettuce pool 缓存连接池 --&gt;</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.apache.commons<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>commons-pool2<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>com.alibaba<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>fastjson<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>commons-codec<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>commons-codec<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.apache.commons<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>commons-lang3<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>




<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependencies</span><span class="token punctuation">&gt;</span></span>

</プロジェクト>

订单实体Order

package com.java1234.entity;

/**注文テーブルエンティティ

  • @著者 java1234_Xiao Feng

  • @サイト www.java1234.com

  • @company 南通暁峰ネットワーク技術有限公司

  • @create 2021-07-13 10:26
    */
    public class 注文 {

    private integer id ; //编号

    private String orderNo; // 订单号< /span>

    private Integer userId; // 用户编号

    private integer count ; // /span>

    private Integer amount; // 购买金额< /span>

    private string beree ; //あ>

    public integer } ; id return {

    public void setid }; id=id .これ{ ) id

    public string }; orderNoreturn{

    public void setOrderNo(String orderNo) {
    これ.注文番号 = 注文番号;
    }

    public integer } ; userid return {

    public void setUserId(整数 userId) {
    これ.ユーザー ID = ユーザー ID;
    }

    public integer }; countreturn{

    public void setCount(Integer count {
    これ count = count ;
    }

    public 整数 getAmount() {
    返品 金額;
    }

    public void setAmount(Integer金額 {
    これ amount = amount;
    }

    public string getRemark {
    return

    public void setRemark 文字列 vere {
    これ bere = vere ;
    }
    }

账户实体Account

package com.java1234.entity;

/**

  • ユーザーアカウントテーブル

  • @著者 java1234_Xiao Feng

  • @サイト www.java1234.com

  • @company 南通暁峰ネットワーク技術有限公司

  • @create 2021-07-13 10:36
    */
    public class アカウント {

    private integer id ; //编号

    private Integer userId; // 用户编号

    private Integer balance; // 账户余额

    private string beree ; //あ>

    public integer } ; id return {

    public void setid }; id=id .これ{ ) id

    public integer } ; userid return {

    public void setUserId(整数 userId) {
    これ.ユーザー ID = ユーザー ID;
    }

    public 整数 getBalance() {
    返却 残高;
    }

    public void setBalance(整数 残高) {
    これ残高 = 残高;
    }

    public string getRemark {
    return

    public void setRemark 文字列 vere {
    これ bere = vere ;
    }
    }

2.5シータオーダーサブプロジェクト建設

seata-orderサブプロジェクトは主に注文サービスを提供し、注文を生成します。

プロジェクトの構造:
ここに画像の説明を挿入します

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>seatatest</artifactId>
        <groupId>com.java1234</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>seata-order</artifactId>
  <dependencies>
        <dependency>
            <groupId>com.java1234</groupId>
            <artifactId>seata-common</artifactId>
        </dependency>
    </dependencies>
</project>

application.yml

server:
  port: 8081
  servlet:
    context-path: /

spring:
datasource:
type com.alibaba.druid.pool.druiddatasource
driver-class-name 注文 - seata name application 8848 127.0.0.1 server-addr discovery nacos 123456 パスワード root username servertimezone = asia/shanghai 3306/db_order // localhost mysql jdbc:
url com.mysql.cj.jdbc.Driver







mybatis:
マッパーの場所: クラスパス*.xmlmybatis/mapper/:

启动类OrderApplication

package com.java1234;

インポート org mybatis spring 注釈 args,class.(run.SpringApplication) args][(mainvoidstatic。 > { OrderApplication class public “ com.java1234.mapper” @mapperscan discovery クライアントクラウド springframework org インポート; autoconfigure boot springフレームワーク org インポート boot springframework org インポート; ;}}











OrderMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java1234.mapper.OrderMapper">
    <select id="createOrder" parameterType="com.java1234.entity.Order" >
        insert into t_order values(null,#{orderNo},#{userId},#{count},#{amount},#{remark})
    </select>
</mapper>

OrderMapperインターフェース:

package com.java1234.mapper;
import com.java1234.entity.Order;
/**
 * @author java1234_小锋
 * @site www.java1234.com
 * @company 南通小锋网络科技有限公司
 * @create 2021-07-13 10:43
 */
public interface OrderMapper {
    
    
<span class="token comment">/**
 * 创建订单
 * &#64;param order
 */</span>
<span class="token keyword">void</span> <span class="token function">createOrder</span><span class="token punctuation">(</span><span class="token class-name">Order</span> order<span class="token punctuation">)</span><span class="token punctuation">;</span>

}

OrderServiceインターフェース:

package com.java1234.service;

インポート com.java1234.エンティティ.注文;

/**

  • 注文サービスインターフェース

  • @著者 java1234_Xiao Feng

  • @サイト www.java1234.com

  • @company 南通暁峰ネットワーク技術有限公司

  • @create 2021-07-14 11:00
    */
    public interface オーダーサービス {

    /**

    • 注文の作成
    • @param order
      */
      void createOrder(< /span> ; 注文注文

}

OrderServiceImpl実装クラス:

package com.java1234.service.impl;

インポート com java1234 entity.Order;
import com ; サービスステレオタイプ springフレームワーク org インポート; autowired annotation springフレームワーク org インポート; Orderservice java1234


/**

  • @著者 java1234_Xiao Feng

  • @サイト www.java1234.com

  • @company 南通暁峰ネットワーク技術有限公司

  • @create 2021-07-14 11:02
    */
    @Service(OrderServiceImpl< /span>{ OrderService実装classpublic)“orderService”

    @Autowired
    private OrderMapper orderMapper;

    @Override
    public void createOrder( orderMapper)}};オーダー(createOrder.{ ) 注文注文



OrderController

package com.java1234.controller;

インポート com.java1234.エンティティ.注文;
インポート com.java1234.サービス.OrderService;
インポート 組織.スプリングフレームワーク.ビーン.ファクトリー.アノテーション.自動接続;
インポート 組織.springframework .ウェブ.バインド.アノテーション.ポストマッピング;
インポート 組織.スプリングフレームワーク.ウェブ.バインド.アノテーション. RequestBody;
インポート 組織 springframework.ウェブ.バインド.アノテーション.RequestMapping;
インポート 組織.springframework.ウェブ.バインド.アノテーション.RestController;

インポート java.util. UUID;

/**

  • @著者 java1234_Xiao Feng

  • @サイト www.java1234.com

  • @company 南通暁峰ネットワーク技術有限公司

  • @create 2021-07-14 11:13
    */
    @RestController
    @RequestMapping{ オーダーコントローラークラス公開)"/seata"(

    @Autowired
    private OrderService orderService;

    /**

    • 注文の作成
    • @パラメータの順序
    • @return
      */
      @PostMapping(" /createOrder")
      public boolean createOrder(@RequestBody Order order){
      System.out.println(“order:”+ordersetOrderNo() }};truereturn ;)order(createOrder . orderService// 生成订单ID;)(toString.)randomUUID.UUID(. order;)





2.6 Seataアカウントサブプロジェクトの構築

seata-accountサブプロジェクトは主に口座サービスを提供し、注文に基づいてお金を引き落とします。

プロジェクトの構造:
[外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムが存在する可能性があります。画像を保存して直接アップロードすることをお勧めします (img-tNBgKCD3-1627344238304) (C:\Users\java1234\Desktop\Distributed Transactions\Courseware) \Alibaba 分散トランザクション フレームワーク Seata courseware.assets\image-20210724063103151.png)]

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>seatatest</artifactId>
        <groupId>com.java1234</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>seata-account<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependencies</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>com.java1234<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>seata-common<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependencies</span><span class="token punctuation">&gt;</span></span>

</プロジェクト>

application.yml

server:
  port: 8082
  servlet:
    context-path: /

スプリング:
データソース:
タイプ: com.alibaba.druid.pool.DruidDataSource
ドライバー クラス名::::account- seata名前:アプリケーション8848 127.0.0.1:server-addr:ディスカバリー:ナコス:クラウド123456:パスワード ルート:ユーザー名serverTimezone=Asia/Shanghai?3306/db_account//localhost:mysql: jdbc:
url com.mysql.cj.jdbc.Driver







mybatis:
マッパーの場所: クラスパス*.xmlmybatis/mapper/:

AccountApplicationスタートアップクラス:

package com.java1234;

import org.mybatis. spring.annotation.MapperScan ;
import org.springframework .boot.SpringApplication;
インポート 組織.springframework. boot.autoconfigure.SpringBootApplication ;
インポート 組織.springframework .クラウド.クライアント.ディスカバリー.EnableDiscoveryClient;

@SpringBootApplication
@MapperScan(“com.java1234.mapper”)
@EnableDiscoveryClient
パブリック クラス AccountApplication< a i=9>{

<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token class-name">SpringApplication</span><span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span><span class="token class-name">AccountApplication</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">,</span> args<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

}

AccountMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java1234.mapper.AccountMapper">
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">&#61;</span><span class="token punctuation">&#34;</span>decrease<span class="token punctuation">&#34;</span></span> <span class="token attr-name">parameterType</span><span class="token attr-value"><span class="token punctuation attr-equals">&#61;</span><span class="token punctuation">&#34;</span>Map<span class="token punctuation">&#34;</span></span> <span class="token punctuation">&gt;</span></span>
    UPDATE t_account SET balance&#61;balance-#{amount} WHERE userId&#61;#{userId}
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>select</span><span class="token punctuation">&gt;</span></span>

</マッパー>

AccountMapperインターフェース:

package com.java1234.mapper;

インポート java.util.地図;

/**

  • アカウントマッパーインターフェイス

  • @著者 java1234_Xiao Feng

  • @サイト www.java1234.com

  • @company 南通暁峰ネットワーク技術有限公司

  • @create 2021-07-13 10:43
    */
    パブリック インターフェース AccountMapper {

    /**

    • 账户扣钱
      */
      無効 減少(< /span>;)地図地図

}

AccountServiceインターフェース:

package com.java1234.service;

インポート java.util.地図;

/**

  • アカウントサービスインターフェース

  • @著者 java1234_Xiao Feng

  • @サイト www.java1234.com

  • @company 南通暁峰ネットワーク技術有限公司

  • @create 2021-07-15 12:58
    */
    パブリック インターフェース アカウントサービス {

    /**

    • 账户扣钱
      */
      無効 減少(< /span>}< /span>;)地図地図

AccountServiceImplインターフェース実装クラス:

package com.java1234.service.impl;

インポート com.java1234.マッパー.AccountMapper;
インポート com.java1234.サービス.AccountService;
インポート 組織.スプリングフレームワーク.ビーン.ファクトリー.アノテーション.自動接続;
インポート 組織.springframework .ステレオタイプ.サービス;

インポート java.util.地図;

/**

  • アカウントサービス実装クラス

  • @著者 java1234_Xiao Feng

  • @サイト www.java1234.com

  • @company 南通暁峰ネットワーク技術有限公司

  • @create 2021-07-15 13:00
    */
    @Service(AccountServiceImpl< /span>{ AccountService実装クラスパブリック)“accountService”

    @Autowired
    プライベート AccountMapper accountMapper;

    @Override
    public void decrease( accountMapper)}};マップ(減少.{ ) マップマップ



AccountController

package com.java1234.controller;

インポート com.java1234.サービス.AccountService;
インポート org.springframework.Beans .ファクトリー.アノテーション. autowired ;
インポート org springframework web ;RestController.annotation.bind.web.springframework.orgimport;RequestParam.annotation.bind.web.springframework. org インポート; requestmapping bind web org インポート annotation


インポート java util hashmap ;
インポート java util マップ;

/**

  • アカウントコントローラー

  • @著者 java1234_Xiao Feng

  • @サイト www.java1234.com

  • @company 南通暁峰ネットワーク技術有限公司

  • @create 2021-07-15 13:06
    */
    @RestController
    @RequestMapping{ アカウントコントローラークラスパブリック)"/アカウント"(

    @autowired
    private accountservice accountservice ;

    /**

    • 给指定用户账户扣钱

    • @パラメータの量

    • @param ユーザー ID

    • @return
      */
      @PostMapping(" /decrease")
      public boolean decrease(@RequestParam(“金額”) 整数 金額, @RequestParam()< /span>.< /span>userId; +",userId:"+金額+“金額:”(printlnアウト.システム{ userId整数)“userId”

      マップ<文字列オブジェクトハッシュマップ;)ユーザー ID,“userId”(put. マップ;)金額,“金額”(置く. マップ; )(><新しい= マップ>

      accountService.減少(マップ);
      return true;

    }

}

2.7 Seata-web サブプロジェクトの構築

seata-webサブプロジェクトは主にクライアントの注文リクエストを処理し、リモートで注文を呼び出すふりをし、アカウント サービス インターフェイスを処理し、最終的に注文処理を完了します。

プロジェクトの構造:

[外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムが存在する可能性があります。画像を保存して直接アップロードすることをお勧めします (img-Cq1nSqoP-1627344294771) (C:\Users\java1234\Desktop\Distributed Transactions\Courseware) \Alibaba 分散トランザクション フレームワーク Seata courseware.assets\image-20210724063910966.png)]

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>seatatest</artifactId>
        <groupId>com.java1234</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>seata-web<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependencies</span><span class="token punctuation">&gt;</span></span>

    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>com.java1234<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>seata-common<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>

    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.cloud<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-cloud-starter-openfeign<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependencies</span><span class="token punctuation">&gt;</span></span>

</プロジェクト>

application.yml

server:
  port: 80
  servlet:
    context-path: /

:
:
ナコス:
検出:
サーバー アドレス:ウェブ-:名前: アプリケーション8848: 127.0.0.1


WebApplication

package com.java1234;

インポート 組織.springframework.ブート.SpringApplication;
インポート org.springframework.ブート.自動構成.SpringBootApplication;
インポート 組織.springframework.ブート.自動構成.jdbc .DataSourceAutoConfiguration;
インポート 組織.スプリングフレームワーク.クラウド.クライアント.ディスカバリ.EnableDiscoveryClient ;
インポート 組織.springframework .クラウド.公然偽装. FeignClients を有効にする;

@SpringBootApplication(除外= { { )クラスパブリック@EnableDiscoveryClient)“com. java1234.feign”=basePackages (@EnableFeignClients}クラス.DataSourceAutoConfiguration


<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token class-name">SpringApplication</span><span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span><span class="token class-name">WebApplication</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">,</span> args<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

}

OrderFeignService

package com.java1234.feign;

インポート com.java1234.エンティティ.注文;
インポート 組織.スプリングフレームワーク.クラウド.オープンフェイン.フェイグクライアント;
インポート 組織.springframework.ウェブ.バインド.アノテーション.ポストマッピング;
インポート 組織.スプリングフレームワーク.ウェブ.バインド.アノテーション.リクエスト本文;

/**

  • 注文インターフェイス偽リモート呼び出し

  • @著者 java1234_Xiao Feng

  • @サイト www.java1234.com

  • @company 南通暁峰ネットワーク技術有限公司

  • @create 2021-07-16 10:55
    */
    @FeignClient({ OrderFeignServiceインターフェースパブリック)「seata-order」

    /**

    • 注文の作成
    • @パラメータの順序
    • @return
      */
      @PostMapping(" /seata/createOrder")
      public boolean createOrder< a i=9>(@RequestBody注文 注文) ;

}

AccountFeignService

package com.java1234.feign;

インポート 組織.springframework.クラウド.オープンフェイン.フェイグクライアント;
インポート 組織.springframework .ウェブ.バインド.アノテーション.ポストマッピング;
インポート 組織.スプリングフレームワーク.ウェブ.バインド.アノテーション. RequestParam;

/**

  • アカウントインターフェイスのリモート呼び出しを装う

  • @著者 java1234_Xiao Feng

  • @サイト www.java1234.com

  • @company 南通暁峰ネットワーク技術有限公司

  • @create 2021-07-16 10:55
    */
    @FeignClient({ AccountFeignServiceインターフェースパブリック)「seata-account」

    /**

    • 口座からお金を差し引く
    • @パラメータの量
    • @param ユーザー ID
    • @return
      */
      @PostMapping(" /account/decrease")
      public boolean decrease< a i=9>(@RequestParam(“金額”)(< /span>; ) userId整数)“userId”@RequestParam, 金額整数

}

WebController

package com.java1234.controller;

インポート com.java1234.エンティティ.注文;
インポート com.java1234..AccountFeignService;
インポート com .java1234.偽装. OrderFeignService;
インポート 組織スプリングフレームワーク.ビーンズ.ファクトリー.注釈.自動接続;
インポート 組織.springframework.ウェブ.バインド.アノテーション.ポストマッピング;
インポート 組織.スプリングフレームワーク.ウェブ.バインド.アノテーション.RestController ;

/**

  • Web レスト インターフェイス

  • @著者 java1234_Xiao Feng

  • @サイト www.java1234.com

  • @company 南通暁峰ネットワーク技術有限公司

  • @create 2021-07-15 16:32
    */
    @RestController
    public { WebControllerクラス

    @Autowired
    private OrderFeignService orderFeignService;

    @Autowired
    private AccountFeignService accountFeignService;

    /**

    • 注文 1、注文 2 の作成、口座引き落とし
    • @パラメータの順序
    • @return
      */
      @PostMapping(" /shopping")
      public boolean ショッピング(注文注文){
      orderFeignService.createOrder(order); // 创建订单
      accountFeignService. 減少(注文.getAmount ()注文getUserId()); // 账户扣钱
      return true;
      }

}

2.8 郵便配達員のテスト

まず Nacos サービス登録センターを起動します:
ここに画像の説明を挿入します
プロジェクトの起動:
[外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムが存在する可能性があります。画像を保存して直接アップロードすることをお勧めします (img-A3gpipEl-1627344382468) (C:\Users\java1234\Desktop\Distributed Transactions\Courseware) \Alibaba 分散トランザクション フレームワーク Seata courseware.assets\image-20210724064801385.png)]
Nacos コンソール:
[外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムが存在する可能性があります。画像を保存して直接アップロードすることをお勧めします (img-EZOpYCXU-1627344382468) (C:\Users\java1234\Desktop\Distributed Transactions\Courseware) \Alibaba 分散トランザクション フレームワーク Seata courseware.assets\image-20210724064838233.png)]
サービス登録が成功しました。

インターフェイスのテスト: http://localhost/shopping
[外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムが存在する可能性があります。画像を保存して直接アップロードすることをお勧めします (img-ffYdCFNZ-1627344382469) (C:\Users\java1234\Desktop\Distributed Transactions\Courseware) \Alibaba 分散トランザクション フレームワーク Seata courseware.assets\image-20210724064433195.png)]
インターフェイスのテスト OK:

注文テーブルは注文を生成します。
[外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムが存在する可能性があります。画像を保存して直接アップロードすることをお勧めします (img-poFz4Jnh-1627344382469) (C:\Users\java1234\Desktop\Distributed Transactions\Courseware) \Alibaba 分散トランザクション フレームワーク Seata courseware.assets\image-20210724064906931.png)]

口座テーブルの ID=1 のジャック口座は、180 元を正常に引き落としました。
[外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムが存在する可能性があります。画像を保存して直接アップロードすることをお勧めします (img-1GHl90LQ-1627344382469) (C:\Users\java1234\Desktop\Distributed Transactions\Courseware) \Alibaba 分散トランザクション フレームワーク Seata courseware.assets\image-20210724064924478.png)]

4 分散トランザクション問題のシミュレーション

複数のサービス呼び出しが進行中の場合、1 つ以上のサービスが実行に失敗し、異常な状態が発生し、その結果データの不整合が発生し、分散トランザクションの問題が発生します。

この問題をシミュレーションしてみましょう。操作中に、口座引き落とし操作は失敗します。
[外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムが存在する可能性があります。画像を保存して直接アップロードすることをお勧めします (img-7D1QrcqZ-1627344505938) (C:\Users\java1234\Desktop\Distributed Transactions\Courseware) \Alibaba 分散トランザクション フレームワーク Seata courseware.assets\image-20210724065542506.png)]
内部の seata-account を変更してみましょう。AccountControllerクラスdecreaseメソッド:

/**
 * 给指定用户账户扣钱
 * @param amount
 * @param userId
 * @return
 */
@PostMapping("/decrease")
public boolean decrease(@RequestParam("amount")Integer amount, @RequestParam("userId")Integer userId)throws Exception{
    
    
    System.out.println("amount:"+amount+",userId:"+userId);
<span class="token keyword">if</span><span class="token punctuation">(</span>userId<span class="token operator">&#61;&#61;</span><span class="token keyword">null</span> <span class="token operator">||</span> userId<span class="token operator">&#61;&#61;</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
    <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Exception</span><span class="token punctuation">(</span><span class="token string">&#34;模拟异常&#34;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token class-name">Map</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">,</span><span class="token class-name">Object</span><span class="token punctuation">&gt;</span></span> map<span class="token operator">&#61;</span><span class="token keyword">new</span> <span class="token class-name">HashMap</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
map<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">&#34;amount&#34;</span><span class="token punctuation">,</span>amount<span class="token punctuation">)</span><span class="token punctuation">;</span>
map<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">&#34;userId&#34;</span><span class="token punctuation">,</span>userId<span class="token punctuation">)</span><span class="token punctuation">;</span>

accountService<span class="token punctuation">.</span><span class="token function">decrease</span><span class="token punctuation">(</span>map<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>

}

userId=1 の場合、シミュレーションは例外をスローし、以下は実行されません。

まずデータベース データを元の状態に復元してから、postman でテストします。

[外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムが存在する可能性があります。画像を保存して直接アップロードすることをお勧めします (img-2qn7BF9w-1627344505939) (C:\Users\java1234\Desktop\Distributed Transactions\Courseware) \Alibaba 分散トランザクション フレームワーク Seata courseware.assets\image-20210724070731831.png)]
500 例外が発生します。

この時点で、データベースを確認したところ、t_order テーブルにデータがあり、注文が生成されていることがわかりました。
[外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムが存在する可能性があります。画像を保存して直接アップロードすることをお勧めします (img-Pa67gR9n-1627344505940) (C:\Users\java1234\Desktop\Distributed Transactions\Courseware) \Alibaba Distributed Transactions Framework Seata courseware.assets\image-20210724070823410.png)]
t_account テーブルを再度確認すると、データは変更されていません。
[外链图片图片、源站、源站源站有有防盗链、建议建议建议将图片保存保存(img-yycqzg6z-16273445942)(c:\ uses \ java1234 \ desktop \分布式\框架シート课件.assets\image-20210724070929838.png)]
この場合、ビジネスにおけるデータの不整合の問題、つまり分散トランザクションの問題が発生します。この問題を解決する必要があります。

分散トランザクションの 5 つの一般的なソリューション

5.1 CAP理論

CAP 理論: 分散システムが一貫性、可用性、パーティションのフォールト トレランスという 3 つの基本要件を同時に満たすことは不可能であり、同時に満たせるのは最大でも 2 つだけです。

一貫性 (C): 複数のコピー間でデータの一貫性を維持できるかどうか。

可用性(a):システムが提供するサービスが一貫して利用可能である必要があることを意味します。各ユーザーの要求について、結果は常に限られた時間内に返されます。時間を超えた場合、システムは利用できないと見なされます。

パーティションフォールトトレランス (P): 分散システムは、ネットワークパーティション障害が発生した場合でも、ネットワーク環境全体に障害が発生しない限り、一貫性と可用性を満たす外部サービスを確実に提供できる必要があります。

5.2 CAP定理の応用

Give up P(CA): If you want to avoid partition fault tolerance problems in the system, a simpler approach is to put all data (or data related to things) on a distributed node, so although it cannot Guarantee 100% that the system問題が発生することはありませんが、少なくともネットワークの分断によって引き起こされる悪影響には遭遇しません。

Give up A (CP): The approach is that once the system encounters a network partition or other failure, the affected services need to wait for a certain period of time. During the application waiting period, the system cannot provide normal services to the outsideつまり、利用できません。

諦めC(AP): ここでいう整合性の放棄とは、データの整合性が全く必要ないという意味ではなく、データの強整合性を放棄し、データの最終的な整合性を保持することを意味します。

5.3 BASE理論

BASE は基本的に利用可能で、ソフトな状態であり、結果的に整合性があります。是对CAP中一致性和可用性权限的结果,是基于CAP定理演化而来的,核心思想是即使无法做到强一致性,但每个应用都可以根据自身的业务特定,采用适当的方式来使系统达到最终一致性

5.4 2PC提出

  • 2 フェーズ コミット プロトコルは、トランザクション送信プロセスを 2 つの段階 (トランザクション要求の送信とトランザクション送信の実行) に分割します。

フェーズ1:トランザクションリクエストを送信します

  • トランザクションクエリ:コーディネーターはトランザクションコンテンツをすべての参加者に送信し、トランザクション提出操作を実行できるかどうかを尋ね、各参加者の応答を待ち始めます
  • トランザクションの実行: 各参加ノードはトランザクション操作を実行し、元に戻すおよびやり直しの情報をトランザクション ログに記録します。
  • 参加者がトランザクション操作を正常に実行する場合、はい応答がコーディネーターに返還され、トランザクションを実行できることを示します。トランザクションが正常に実行されない場合、コーディネーターにNO応答が返され、トランザクションができないことを示します。処刑される。
  • 一部のコミットが第2フェーズで行われるフェーズは、投票段階と呼ばれます。つまり、各参加者は次のトランザクション提出操作を継続できるかどうかを示すために投票します。

フェーズ 2: トランザクションの送信を実行する

  1. コーディネーターがすべての参加者から「はい」応答を受信すると、トランザクションのコミットが実行されます。

  2. コミット リクエストの送信: コーディネーターは、すべての参加ノードにコミット リクエストを発行します。

  3. トランザクションの提出:コミットリクエストを受け取った後、参加者はトランザクション提出操作を正式に実行し、提出を完了した後、トランザクションの実行中に占有されているトランザクションリソースを放棄します。

  4. 逆事のハンドハンドリングの結果: 参加者がハンドハンドリングを完了した後、承認者に ACK メッセージを送信します。

  5. トランザクションを完了する: コーディネーターは、すべての参加者から ACK メッセージを受信した後、トランザクションを完了します。

中断事务

  • 参加者がフィードバックしている場合、コーディネーターへの応答がない場合、またはコーディネーターがタイムアウトを待った後、すべての参加者からフィードバック応答を受信できない場合、トランザクションは中断されます。

  • ロールバックリクエストの送信:コーディネーターは、すべての参加者ノードにロールバック要求を発行します

  • 事の戻し: 参加者は、ロールバック要求を受信した後、それを使用して、第 1 段階で承認された元に戻す情報の実行イベントを実行し、事の実行中に使用されたリソースを解放します。

  • 反事事务回滓結果:事事完了後、协调者にACKメッセージを送信します。

  • 事態の中断:参加者がすべての参加者の応答の Ack メッセージを受信した後、事態の中断が完了します。

長所と短所

  • 原理简单、实现方便

  • 缺点は同步障壁、单点问题、脑裂、保守

5.5 3PC提交

  • 3 フェーズ コミットは、3 フェーズ コミット プロトコルとも呼ばれ、2 フェーズ コミット (2PC) の改良版です。

  • 与两阶段提交不同的是,三阶段提交有两个改动点。タイムアウト機構を導入します。同时在协调者和参与者中都引入超时机制。在第一阶段和第二阶段中插入一个准备阶段。保证了在最后提交阶段之前各参与节点的状态是一致的。

  • 3 段階の送信には、CanCommit、PreCommit、および DoCommit の 3 つの段階があります。

5.6 TCC 配布式事务

  • TCC は 2 段階のサービス プログラミング モデルであり、その 3 つのメソッド (Try、確認、およびキャンセル) はすべてビジネス コーディングによって実装されます。

  • TCC では、各ブランチ トランザクションに、前処理 Try、確認 confirm、およびキャンセル Cancel の 3 つの操作を実装する必要があります。

  • 業務確認やリソース予約などの操作を試してみる

  • 確認業務確認操作を行います

  • Cancel は Try の逆の操作、つまりロールバック操作を実装します。

  • TM は最初にすべてのブランチ トランザクションの Try 操作を開始します。いずれかのブランチ トランザクションの Try 操作が失敗した場合、TM はすべてのブランチ トランザクションの Cancel 操作を開始します。Try 操作がすべて成功した場合、TM はすべてのブランチ トランザクションの confirm 操作を開始します。 , where Confirm If the /Cancel operation fails, TM will retry.

TCCの3つの段階

  • Try フェーズは、做业务検査 (一致性) およびソース確保 (分離) であり、このフェーズは単なる最初の操作であり、その後の確認によって完全なトラフィックを構成することはできません。

  • フェーズが承認取引中であることを確認し、トライフェーズのすべての分別業務が成功した後に実行を開始します。通常の場合、TCC を使用して、フェーズが失敗しないことを確認します。つまり、ただ試行成功、確認が一定成功、若確認フェーズが真のものです。取り外し、重機製造または手動処理の導入が必要

  • キャンセル段階は、トラフィックの実行中に状態に戻る必要があり、分別の取り消しを実行し、リソースの確保を保留します。通常の場合、TCC が採用されており、キャンセル段階も真の機能であると見なされており、若いキャンセル段階の真の出力であるため、組み込みが必要です重機制または人工処理

  • TM 事管理者: TM 事管理者は、独立したサービスとして実現することもできますが、完全なローカル 事の発行者が TM の色を担当することもできます。TM の独立性は、公共のコンポーネント用であり、システムの構造とパッケージを考慮するためです。

  • TM は、グローバル トランザクションの開始時にグローバル トランザクション レコードを生成します。グローバル トランザクション ID は、分散トランザクション呼び出しチェーン全体を通じて実行され、トランザクション コンテキストの記録、ステータスの追跡および記録に使用されます。確認とキャンセルが失敗した場合は、再試行する必要があるため、 they need to be idempotent.

TCC の 3 つの例外処理状況

べき等処理

  • 因为网络抖动等原因,分布式事务框架可能会重复调用同一个分布式事务中的一个分支事务的二阶段接口。したがって、2フェーズインターフェイスは、ブランチトランザクションの確認/キャンセルが必要である必要があります。如果二阶段接口不能保证幂等性,则会产生严重的问题,造成资源的重复使用或者重复释放,进而导致业务故障。
  • iDempotentの問題については、通常の方法は、リプレイ攻撃を防ぐために、等容量フィールドを導入することです。分散トランザクションフレームワークにおける識別問題の場合、この武器も使用できます。
  • 幂等记录的插入时机是参与者的Try方法,此时的分支事务状态会被初始化为INIT。次に、第2段階の確認/キャンセルが実行されると、そのステータスが確認/ロールバックされるように設定されます。
  • TC が第 2 フェーズ インターフェイスを繰り返し呼び出すと、参加者はまずトランザクション ステータス管理テーブルの対応するレコードを取得して、トランザクション ステータスを表示します。ステータスが CONFIRMED/ROLLBACKED の場合は、参加者がその義務を完了し、再度実行する必要がないことを意味します。冪等の成功結果を TC に直接返すことで、分散トランザクションの促進に役立てることができます。

空のロールバック

  • Try メソッドが実行されていない場合は、2 段階の Cancel メソッドが使用されます。Cancel メソッドは、その時点で Try が実行されていないことを通知する必要があります。 NextCancel は空回帰に属し、Try が実行済みの場合に実行されるのは通常の回帰です。
  • 要应对空回滚的问题,就需要让参与者在二阶段的Cancel方法中有办法识别到一阶段的Try是否已经执行。明らかに、トランザクションステータスコントロールテーブルを使用してこの機能を実装できます。
  • Try メソッドが正常に実行されると、1 つのステータスが入力され、その後 2 段階の Cancel メソッドが使用されると、そのレジスタが INIT 状態にあるかどうかが、ステータス制御テーブルによって判断されます。 INIT は、フェーズが正常に実行されたことを示し、通常のリプレイス操作を実行して、保留されているリソースを解放します。表示されない場合は、フェーズが未実行であることを示し、今回はリソースを解放しません。

资源悬挂

  • 問題:TCロールバックトランザクションが第2フェーズを呼び出して空のロールバックを完了した後、第1フェーズは正常に実行されます。
  • 解決策:トランザクションステータス制御レコードは制御方法として使用されます。第2段階でレコードが見つからない場合、レコードが挿入されます。最初の段階では、レコードが存在するかどうかを確認します。

TCCと2PCの比較

  • 2PC は通常、すべての DB 層面で処理されますが、TCC はアプリケーション層面で処理され、このような分散ビジネスの実現方法は、アプリケーション層のクラッシュを軽減するために、トラフィック アクセスを介して実行される必要があります。 ,吞吐量の増加が可能になります
  • 欠点は、アプリケーションにとって非常に煩わしいことであり、ビジネス ロジックの各ブランチで Try、confirm、cancel の 3 つの操作を実装する必要があることです。さらに、その実装は比較的難しく、ネットワークの状態やシステム障害のさまざまな障害理由に応じて、さまざまなロールバック戦略を実装する必要があります。

5.7 メッセージキューは信頼性の高いメッセージの結果整合性を実現します

  • 信頼できるメッセージの最終的な一貫性は、メッセージ ミドルウェアを通じてプロデューサーからコンシューマーまでのメッセージの一貫性を保証することです。
  • RocketMQ は主に 2 つの機能、つまりメッセージを受信する側のアトム性の問題に対処します。
  • 信頼性の高いメッセージ結果整合性トランザクションは、実行サイクルが長く、リアルタイム要件が低いシナリオに適しています。メッセージ メカニズムの導入後は、同期トランザクション操作がメッセージ実行に基づいて非同期操作になり、分散トランザクションでの同期ブロック操作の影響が回避されます。 Achieved decoupling of two services

[External link image transfer failed. The source site may have an anti-leeching mechanism. It is recommended to save the image and upload it directly (img-1BzbttBD-1627344623638) (C:\Users\java1234\Desktop\Distributed Transactions\Courseware \Alibaba 分散トランザクション フレームワーク Seata courseware.assets\image-20210724075536330.png)]

5.8 ベストエフォートに関する通知

最大努力通知と可用メッセージの一致性とは異なるもの

  • 信頼できるメッセージの一貫性。通知の開始側は、メッセージが送信され、通知の受信側に送信されることを確認する必要があります。メッセージの信頼性は、通知の開始側によって保証されます。
  • ベストエフォート型通知では、通知を行う側が受信側に業務処理結果を通知するために最善を尽くしますが、メッセージが受信されない場合があり、このとき受信側は通知側のインターフェースを能動的に呼び出す必要があります。 to query the business. The key to notification reliability lies in the reception Notifying party

両方のアプリケーションシナリオ

  • メッセージの一致性は、取引手順の内容が一致し、取引が完了することを意味します。
  • ベストエフォート型通知は、取引後の通知事項、つまり取引結果を確実に通知することに重点を置いています。

MQ に基づく ack機械制の最大努力通知
[External link image transfer failed. The source site may have an anti-leeching mechanism. It is recommended to save the image and upload it directly (img-vjTMkNFx-1627344623639) (C:\Users\java1234\Desktop\Distributed Transactions\Courseware \Alibaba 分散トランザクション フレームワーク Seata courseware.assets\image-20210724075807977.png)]

  • MQ は MQ の ack メカニズムを使用してメッセージ通知を受信側に送信し、イニシエーターは通常のメッセージを MQ に送信します。
  • 通知を受信し、MQ を監視し、メッセージを受信し、ビジネス処理が完了したら ACK で応答します。
  • 通知を受信した場合、ACK が返されない場合、MQ は時間間隔で通知を繰り返し、徐々に大きな通知間隔を設定します。
  • このソリューションは、内部マイクロサービス間の通知には適していますが、外部プラットフォームでの通知には適していません。

解決策 2: 通知サービスを追加して区に通知を実行し、外部の第三方時間指定を提供する

[外链图片转存失败、源站、源站源站有防盗链、建议建议、建议建议将图片保存保存(img-eohqkkqqccc-16273444623641)(c:\ users \ java1234 \ desktop \±\框架シート课件.assets\image-20210724080420663.png)]

5.9 配布形式事案比分析

  • 2PC に対する最大の批判の 1 つは、2PC がブロッキング プロトコルであるということです。 RM はブランチ トランザクションの実行後、TM の決定を待つ必要がありますが、この時点でサービスはロックされたリソースをブロックします。この設計は、ブロッキング メカニズムと最悪の場合の時間の複雑さの高さにより、トランザクションに関与するサービスの数が増加するにつれて拡張する必要性に適応できず、高い同時実行性と長いサブトランザクション寿命を備えた分散サービスには使用することが困難です。 cycles. middle
  • TCCトランザクション処理プロセスを2PCの2段階の提出と比較すると、2PCは通常、横断障害のDBレベルにあり、TCCはアプリケーションレベルで処理され、ビジネスロジックを通じて実装する必要があります。この分散トランザクションの利点は、アプリケーションがデータ操作の粒度をカスタマイズできるため、ロックの競合を減らし、スループットを改善できることです。欠点は、アプリケーションにとって非常に煩雑であり、ビジネス ロジックの各ブランチで 3 つの操作を実装する必要があることです。さらに、その実装は比較的困難であり、ネットワークのステータスやシステムの障害などのさまざまな障害の理由に従って、さまざまな戦略を実装する必要があります。
  • 可靠消息最终一致性事务适合执行周期长且实时性要求不高的场景。 After the message mechanism is introduced, synchronous transaction operations become asynchronous operations based on message execution, which avoids the impact of synchronous blocking operations in distributed transactions and realizes the decoupling of the two services. Typical scenarios: register to receive points, log in Send coupons等
  • Best-effort notification is the least demanding type of distributed transactions. It is suitable for some businesses with low final consistency and low time sensitivity. It allows the initiating party to fail in business processing and the receiving party to actively handle the failure after receiving the notification, regardless of the initiator. How the notifying party handles the results will not affect the subsequent processing of the notifying party. The notifying party needs to provide a query execution status interface for the receiving notifying party to proofread the results. Typical application scenarios:銀行からの通知、支払い結果の通知など
    [External link image transfer failed. The source site may have an anti-leeching mechanism. It is recommended to save the image and upload it directly (img-nbJeLxs3-1627344623641) (C:\Users\java1234\Desktop\Distributed Transactions\Courseware \ alibaba分散トランザクションフレームワークシートコースウェア。Assets\ Image-2021072407433428.png)]]

6 シータ原理の詳細説明

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。 SEATAは、ユーザーにAT、TCC、SAGA、XAトランザクションモードを提供し、ユーザー向けのワンストップ分散ソリューションを作成します。

6.1 シータの语

TC (トランザクション コーディネーター) - 事务协调者

グローバルおよびブランチ トランザクションのステータスを維持し、グローバル トランザクションの送信またはロールバックを推進します。

TM (トランザクションマネージャー) - トランザクションマネージャー

全局事の開始、転送、または全局事の返送。

RM (リソースマネージャー) - リソースマネージャー

ブランチ トランザクション処理のリソースを管理し、TC と通信してブランチ トランザクションを登録し、ブランチ トランザクションのステータスを報告し、ブランチ トランザクションのコミットまたはロールバックを実行します。

[外链图片图片、源站、源站源站可能有防盗链、建议建议建议建议将图片保存下来(img-8mhhqvv2v2v-1627344942267)(c:\ users \ java1234 \ desktop \±\框架シート课件.assets\image-20210724083939074.png)]

Seata管理配布式事务の典型的な生命周期

  • TM は TC に新しいグローバル トランザクションを開始するように依頼します。 TC生成表示全局事务的XID。
  • XID はマイクロサービスの調整用ブロードキャストを介して送信されます。
  • RM は、ローカル ジグを XID から TC の対応する全ローカル ジグに登録します。
  • TM は、TC の譲渡または XID の返還を要求します。
  • TC は、XID の対応するグローバル トランザクションの下にあるすべてのブランチ トランザクションを駆動して、ブランチのコミットまたはロールバックを完了します。

分散トランザクションは、ブランチ トランザクションのバッチで構成されるグローバル トランザクションであり、通常、ブランチ トランザクションはローカル トランザクションです。

[External link image transfer failed. The source site may have an anti-leeching mechanism. It is recommended to save the image and upload it directly (img-BcFjHmMD-1627344942267) (C:\Users\java1234\Desktop\Distributed Transactions\Courseware \ Alibaba分散トランザクションフレームワークシートコースウェア。Assets\ Image-20210725061327834.png)]]

6.2 ATモード

前提

  • 独自の ACID 案件をサポートする関連タイプのデータベースに基づいています。
  • Java アプリケーションは、JDBC 経由でデータベースにアクセスします。

整体機械化

二段提交议の演变:

  • フェーズ 1: ビジネス データとロールバック ログ レコードが同じローカル トランザクションで送信され、ローカル ロックと接続リソースが解放されます。
  • 第2段:
    • コミットは非同期であり、非常に迅速に完了します。
    • ロールバックは、1 段階のロールバック ログによって逆に補正されます。

写隔离

  • 1つのフェーズでローカルトランザクションをコミットする前に、グローバルロックを最初に取得する必要があります。
  • 拿不到 全局锁 ,不能提交本地事务。
  • 全局锁 的尝试被限制在一定范围内,超出范围将放弃,并回滚本地事务,释放本地锁。

例を挙げて説明しましょう:

2 つのグローバル トランザクション tx1 と tx2 は、それぞれテーブル a の m フィールドを更新します。m の初期値は 1000 です。

tx1 先开始,开启本地事务,拿到本地锁,更新操作 m = 1000 - 100 = 900。本地事务提交前,先拿到该记录的 全局锁 ,本地提交释放本地锁。 tx2 后开始,开启本地事务,拿到本地锁,更新操作 m = 900 - 100 = 800。本地事务提交前,尝试拿该记录的 全局锁 ,tx1 全局提交前,该记录的全局锁被 tx1 持有,tx2 需要重试等待 全局锁

書き込み分離: コミット

tx1 2 フェーズ グローバル コミット、グローバル ロックを解放します。 tx2 はグローバル ロックを取得し、ローカル トランザクションをコミットします。

書き込み分離: ロールバック

tx1 の 2 段階のグローバル ロールバックが発生した場合、tx1 はデータのローカル ロックを再取得し、逆補償更新操作を実行してブランチ ロールバックを実装する必要があります。

At this time, if tx2 is still waiting for the dataglobal lock and holds a local lock, the branch rollback of tx1 will fail 。 The rollback of the branch will be retried until tx2's global lock waits for the lock to time out and gives upglobalロック a> およびローカルトランザクションをロールバックしてローカルロックをリリースすると、TX1のブランチロールバックが最終的に成功しました。

プロセス全体グローバル ロックは、tx1 の終了前に tx1 によって保持されるため、このようなことは起こりませんDirty writing problem.

读隔离

Default global for Seata (AT mode) based on database local transaction isolation levelRead Committed or above The isolation level is committedを読む(committedを読む)

If the application is in a specific scenario, it must require globalread committed. Currently, Seata's method is to use the proxy of the SELECT FOR UPDATE ステートメント。

読み取り分離: 更新用に選択

の[更新ステートメントの選択]の実行は、グローバルロックに適用されます。 /span> . されるまで、クエリはブロックされます。 It will be returned only if it has been submittedが取得されるまで、つまり、関連するデータの読み取りがグローバル ロック は他のトランザクションによって保持されているため、ローカル ロックを解放して (SELECT FOR UPDATE ステートメントのローカル実行をロールバックして)、再試行してください。このプロセス中、

全体的なパフォーマンスに関する考慮事項については、Seataの現在のソリューションはすべての選択されたステートメントをプロキシではなく、選択したステートメントを更新する場合のみです。

動作メカニズム

例を使用して、ATブランチ全体の作業プロセスを説明します。

ビジネステーブル:product

分野 タイプ
ID bigint(20)
名前 varchar(100)
以来 varchar(100)

AT支店トランザクションのビジネスロジック:

update product set name = 'GTS' where name = 'TXC';

最初の段階

プロセス:

  1. 解析SQL:SQLタイプ(更新)、テーブル(製品)、条件(名前=「TXC」)、およびその他の関連情報を取得します。
  2. クエリミラーリング前:クエリステートメントを生成し、分析を通じて取得した条件付き情報に基づいてデータを見つけます。
select id, name, since from product where name = 'TXC';

正面画像を取得します。

ID 名前 以来
1 TXC 2014年
  1. Business SQLを実行:このレコードの名前を「GTS」に更新します。
  2. ミラー後のクエリ: ミラー前の結果に基づいて、主キーを通じてデータを見つけます。
select id, name, since from product where id = 1;

背面の画像を取得します。

ID 名前 以来
1 GTS 2014年
  1. 插入回滚日志:把前后镜像数据以及业务 SQL 相关的信息组成一条回滚日志记录,插入到 UNDO_LOG 表中。
{
    
    
	"branchId": 641789253,
	"undoItems": [{
    
    
		"afterImage": {
    
    
			"rows": [{
    
    
				"fields": [{
    
    
					"name": "id",
					"type": 4,
					"value": 1
				}, {
    
    
					"name": "name",
					"type": 12,
					"value": "GTS"
				}, {
    
    
					"name": "since",
					"type": 12,
					"value": "2014"
				}]
			}],
			"tableName": "product"
		},
		"beforeImage": {
    
    
			"rows": [{
    
    
				"fields": [{
    
    
					"name": "id",
					"type": 4,
					"value": 1
				}, {
    
    
					"name": "name",
					"type": 12,
					"value": "TXC"
				}, {
    
    
					"name": "since",
					"type": 12,
					"value": "2014"
				}]
			}],
			"tableName": "product"
		},
		"sqlType": "UPDATE"
	}],
	"xid": "xid:xxx"
}
  1. Before submitting, register the branch with TC: apply for product the record whose primary key value is equal to 1 in the table global lock< /span>< a i=3> 。
  2. ローカル トランザクションの送信: ビジネス データの更新は、前の手順で生成された UNDO ログと一緒に送信されます。
  3. ローカル トランザクションの送信結果を TC に報告します。

フェーズ 2 - ロールバック

  1. TCのパケットバックリクエストを受信すると、次のような動作が行われる。
  2. XID とブランチ ID を使用して、対応する UNDO LOG レコードを見つけます。
  3. データ チェック: UNDO LOG 内のその後のデータと現在のデータを比較し、異なる場合は、データが現在の完全なローカル アクティビティの外で変更されたことを示す必要があります。別の文書で紹介されています。
  4. UNDO LOG 内の先頭の画像と SQL SQL の関連情報に基づいて生成され、再実行される句:
update product set name = 'TXC' where id = 1;
  1. ローカルトランザクションを送信します。并把本地事务的执行结果(即分支事务回滚的结果)上报给 TC。

フェーズ 2 - 提出

  1. TCからブランチの提出要求を受け取った後、リクエストを非同期タスクキューに入れ、すぐにTCへの提出が成功した結果を返します。
  2. UNDO ジョブ フェーズの分別リクエストは、対応する UNDO LOG を大量に削除します。

付録

回滚日志表

UNDO_LOG テーブル: データベースの種類によって多少の違いがある場合があります。

MySQL を例に挙げます。

分野 タイプ
ブランチID ビギント PK
xid varchar(100)
コンテクスト varchar(128)
ロールバック情報 長い塊
ログステータス タイニーント
ログ作成済み 日付時刻
ログ変更済み 日付時刻
-- 注意此处0.7.0+ 增加字段 context
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;

6.3 TCCモード

概要の説明を確認してください。分散グローバル トランザクションであり、全体が2 フェーズ コミットモデルです。全局事务是由若干分支事务组成的,分支事务要满足 两阶段提交 的模型要求,即需要每个分支事务都具备自己的:

  • 1 段階の準備動作
  • 2 フェーズのコミットまたはロールバックの動作

グローバルトランザクションの概要

2段階の動作モードの違いに基づいて、ブランチトランザクションを自動(枝)トランザクションモードおよび手動 (ブランチ) トランザクション モード

AT モード (参照リンク未定) は、< に基づくローカル ACID トランザクションをサポートします。 a i =4> のリレーショナル データベース:

  • 1 段階の準備動作: ローカル トランザクションでは、ビジネス データの更新と対応するロールバック ログ レコードが一緒に送信されます。
  • 二阶段 commit 行为:马上成功结束,自动 异步批量清理回滚日志。
  • 二阶段 rollback 行为:通过回滚日志,自动 生成补偿操作,完成数据回滚。

同様に、TCC モードは、基礎となるデータ リソースのトランザクション サポートに依存しません。

  • 一阶段 prepare 行为:调用 自定义 的 prepare 逻辑。
  • 二阶段 commit 行为:调用 自定义 的 commit 逻辑。
  • 2 段階のロールバック動作: カスタマイズされたロールバック ロジックを呼び出します。

所谓 TCC 模式,是指支持把 自定义 的分支事务纳入到全局事务的管理中。

6.4 佐賀モード

Saga mode is a long transaction solution provided by SEATA. In Saga mode, each participant in the business process submits a local transaction. When a participant fails, the previous successful participants are compensated. One-stage forward service and The second-stage compensation servicesすべてビジネス開発によって実装されます。

サーガモード図

理論的根拠: ヘクターとケネスが論文「Sagas」を発表 (1987)

适用场景:

  • 長いビジネスプロセスと多くのビジネスプロセス
  • 参加者には、TCC モデルで必要な 3 つのインターフェイスを提供できない他社またはレガシー システム サービスが含まれます。

アドバンテージ:

  • ローカル トランザクションを 1 フェーズで送信し、ロックフリーで高パフォーマンスを実現
  • イベント駆動型アーキテクチャ、参加者は非同期で実行可能、高スループット
  • 補償サービスは簡単に導入できます

欠点:

7分散トランザクションの問題を解決するために、モードソリューションでSeataを適用する

Seata は主に AT モードの強力な整合性ソリューションを推進しているため、前のケースの分散問題を解決するためにこのソリューションを採用します。

7.1 Seata サーバーをダウンロードして実行する

SEATAサーバーアドレス:https://github.com/seata/seata/releases

最新版本 v1.4.2

デモには Windows を使用し、seata-server-1.4.2.zip をダウンロードします。

[External link image transfer failed. The source site may have an anti-leeching mechanism. It is recommended to save the image and upload it directly (img-73EkelmM-1627345127336) (C:\Users\java1234\Desktop\Distributed Transactions\Courseware \ Alibaba分散トランザクションフレームワークSeata Courseware.Assets \ Image-20210724085154578.png)]]

Seata-server 構成ファイル:

seata サーバーのすべての構成は conf フォルダにあります。このフォルダには 2 つのファイルがあり、詳しく説明する必要があります。
Seata サーバーは、デフォルトでファイル (ファイル モード) を使用して、トランザクション ログとトランザクション実行情報を保存します。これは、-m db スクリプト パラメータの形式で指定できます。現在、file と db のみがサポートされています。 . .

ファイル.conf

このファイルは、ストレージ方法、トランザクション情報の透過的な送信のための NIO、およびその他の情報を構成するために使用され、デフォルトでは、registry.conf ファイルのファイル モード構成に対応します。

レジストリ.conf

Seata サーバー コア設定ファイルを使用して、サービスの登録方法と設定の読み取り方法を設定できます。

登録メソッドは現在、file、nacos、eureka、redis、zk、consul、etcd3、sofa などをサポートしています。デフォルトは file で、file.conf 内の登録メソッド情報の読み取りに対応します。

構成情報の読み取り方法は、file、nacos、apollo、zk、consul、etcd3 などをサポートします。デフォルトは file で、file.conf ファイル内の構成の読み取りに対応します。

file.conf1 つ追加しましょうservice構成:

service {
    
    
  #vgroup->rgroup 服务分组  集群分组默认为"default"
  vgroupMapping.my_test_tx_group = "default"
  #only support single node
  default.grouplist = "127.0.0.1:8091"
  #degrade current not support 服务降级达到多次错误不走seata
  enableDegrade = false
  #disable
  disable = false
  #unit ms,s,m,h,d represents milliseconds, seconds, minutes, hours, days, default permanent
  max.commit.retry.timeout = "-1"
  max.rollback.retry.timeout = "-1"
}

ここでのトランザクション グループ化の概念は、最終的には別途説明しますが、主にクラスタ障害時の迅速な切り替えと高可用性を目的としています。

グループ マッピング、クラスター グループ化を構成してから、グループリストを構成し、サーバー アドレスを公開して、呼び出しのためにそれを Seata-client に提供します。

最後に、bin ディレクトリで Seata-server.bat を実行して、seata-server を起動します。
[外链图片转存失败、源站、源站源站有防盗链防盗链、建议建议建议将图片保存保存(img-xh8qjt4d-1627345127337)(c:\ users \ java1234 \ desktop \±\框架シート课件.assets\image-20210724091246627.png)]
OK を開始し、ポートをリッスンします。8091

7.2 各データベースの undo_log ロールバック ログ テーブルを作成する

Seata AT モード仕様に従って、新しい undo_log テーブル、db_account および db_order を作成します。

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=3 DEFAULT CHARSET=utf8

ここに画像の説明を挿入します

7.3 Seata-client Maven 依存関係をプロジェクトに追加する

Seata-common パブリック モジュール プロジェクトに Seata の依存関係を追加するだけでよく、他のサブモジュールはすでにそこにあるので便利です。

<dependency>
	<groupId>com.alibaba.cloud</groupId>
	<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>

7.4 プロジェクトでの分散トランザクションの設定

まず、各プロジェクトは、seata サポートを構成し、構成に従って Seata-server を要求する必要があります。

次に、 @GlobalTransactional アノテーションを使用して、グローバル分散トランザクションを有効にします。

Seata-order サブプロジェクトの application.yml 構成を変更します。

server:
  port: 8081
  servlet:
    context-path: /

スプリング:
データソース:
タイプ: com.alibaba.druid.pool.DruidDataSource
ドライバー クラス名::::注文- シート:名前:アプリケーション my_test_tx_group:tx サービス グループシータ:アリババ8848 127.0.0.1:サーバー アドレス:ディスカバリー:ナコス:クラウド123456:パスワード ルート:ユーザー名serverTimezone=Asia/Shanghai?3306/db_order//localhost:mysql: jdbc:
url com.mysql.cj.jdbc.Driver










mybatis:
マッパーの場所: クラスパス*.xmlmybatis/mapper/:

シート:
サービス:
vgroup マッピンググループリストfalse:グローバル トランザクションを無効にするfalse:有効化 - 劣化8091: 127.0.0.1:デフォルト: デフォルト:my_test_tx_group:





主に、サービス グループ化とクラスター グループ化の構成が追加されます。
[外部リンク画像転送に失敗しました。ソースサイトには、アンチリーチングメカニズムがある場合があります。画像を保存して直接アップロードすることをお勧めします(IMG-8ZSSSM7GM-1627345127338)(c:\ users \ java1234 \ desktop \ Desktop \ Destributions \ courseward \ alibaba分散トランザクションフレームワークシートコースウェア.assets \ image-20210724093057768.png)]]

同様に、seata-account の下の application.yml 構成は次のようになります。

server:
  port: 8082
  servlet:
    context-path: /

spring
dataSource
タイプ: com.alibaba.druid.pool.DruidDataSource
driver-class-name::account - seata name application my_test_tx_group tx-service-group seata alibaba 8848 127.0.0.1 server-addr discovery nacos クラウド123456:password root:usernameserverTimezone=Asia/Shanghai?3306/db_account//localhost:mysql: jdbc:
url com.mysql.cj.jdbc.Driver










mybatis:
マッパーの場所: クラスパス*.xmlmybatis/mapper/:

シート:
サービス:
vgroup マッピンググループリストfalse:グローバル トランザクションを無効にするfalse:有効化 - 劣化8091: 127.0.0.1:デフォルト: デフォルト:my_test_tx_group:





seata-web下のapplication.yml構成:

server:
  port: 80
  servlet:
    context-path: /

spring
cloud
nacos
discovery
server-addr web- name アプリケーション tx-service-group seata alibaba 8848




seata:
service:
vgroup-mappinggrouplist false disable-global-transaction false enable-degrade 8091 127.0.0.1:java1234-seata-server: default:my_test_tx_group:





Seata-Web Project-&GT; WebController-&GT;ショッピング方法、@globalTransactional Annotationを追加
[External link image transfer failed. The source site may have an anti-leeching mechanism. It is recommended to save the image and upload it directly (img-u02jlgaO-1627345127338) (C:\Users\java1234\Desktop\Distributed Transactions\Courseware \ Alibaba分散トランザクションフレームワークSeata Courseware.Assets \ Image-20210724093719123.png)]]

7.5 配布スキームの例

3 つのサブプロジェクトが一緒に実行されます。
[外部リンク画像転送に失敗しました。ソースサイトには、アンチリーチングメカニズムがある場合があります。画像を保存して直接アップロードすることをお勧めします(IMG-PWC1RSBV-1627345127339)(c:\ uses \ java1234 \ desktop \ desktop \ distributed transactions \ courseウェア\ Alibaba分散トランザクションフレームワークシートコースウェア。Assets\ Image-20210725065846770.png)]]
2 つの RM がseata-server に正常に登録されます。
[外部リンク画像転送に失敗しました。ソースサイトには、アンチリーチングメカニズムがある場合があります。画像を保存して直接アップロードすることをお勧めします(IMG-G53YWS4J-1627345127339)(c:\ uses \ java1234 \ desktop \ desktop \ distributed transactions \ courseウェア\ Alibaba分散トランザクションフレームワークSeata Courseware.Assets \ Image-20210725070130991.png)]]
Seata-web プロジェクトの RM と TM が登録されますsuccessfully;
[外部リンク画像転送に失敗しました。ソースサイトには、アンチリーチングメカニズムがある場合があります。画像を保存して直接アップロードすることをお勧めします(IMG-WTMWYFNG-1627345127339)(c:\ uses \ java1234 \ desktop \ Desstop \ Distributed Transactions \ Alibaba分散トランザクションフレームワークSeata Courseware.Assets \ Image-20210725070213646.png)]]
The TM registration for the seata-order project was successful;
ここに画像の説明を挿入します
The TM registration for the seata-account project was successful;

We use postman to send http://localhost/shopping post request
[外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします (img-hzM3vncG-1627345127340) (C:\Users\java1234\Desktop\Distributed Transactions\Courseware) \Alibaba 分散トランザクション フレームワーク Seata courseware.assets\image-20210725065606656.png)]
The execution found that there is no data in the order table and log table, indicating that the test is OK ;

7.6 SETATAの第2段階の提出プロセスの分析

実行は瞬間的であるため、多くの友人は内部の2段階の提出プロセスをまったく感じることができません。

  • フェーズ 1: ビジネス データとロールバック ログ レコードが同じローカル トランザクションで送信され、ローカル ロックと接続リソースが解放されます。
  • 第2段:
    • コミットは非同期であり、非常に迅速に完了します。
    • ロールバックは、1 段階のロールバック ログによって逆に補正されます。

そこで、ロールバック プロセスを確認するために、seata-account プロジェクトにブレークポイントを設定します。
[External link image transfer failed. The source site may have an anti-leeching mechanism. It is recommended to save the image and upload it directly (img-dPdFYEzH-1627345127341) (C:\Users\java1234\Desktop\Distributed Transactions\Courseware \ Alibaba分散トランザクションフレームワークSeata Courseware.Assets \ Image-20210725070725709.png)]]
seata-account プロジェクトのデバッグが開始されます。

再度 Postman テストを行い、すぐに db_order データベース テーブル情報を確認します (送信されたトランザクションはタイムアウトになるとすぐにロールバックされ、情報が表示されないため、取得するのはさらに困難です)。

订单服务実行完遂時候,

db_orderにデータがあります
ここに画像の説明を挿入します
undo_logにもデータがあります
ここに画像の説明を挿入します

第 1 段階のビジネス データとロールバック ログ レコードが同じローカル トランザクションで送信され、ローカル ロックと接続リソースが解放されることを説明します。

その後、送信されたトランザクションがタイムアウトするか、インターフェイス呼び出しで例外が発生した場合、ブランチ トランザクションはロールバック ログに従って直ちに逆補正を実行し、最終的にロールバック ログはクリアされます。

接口调使用が一切正常であれば、日志清空、全局事务提交、次回事务操作を完了します。

8 SEATAトランザクションログMySQL永続性構成

Seata默认事务支持是file文件存储,不怎么好,不方便查看和管理;所以我们一般是db存储;

conf の下にある file.conf 構成ファイルを変更します。
ここに画像の説明を挿入します

モードを「db」に変更します。

その後、下方の mysql 構成を変更して、データベース固有の構成に変更することができます。

他に、global_table、branch_table、lock_table の 3 つのテーブルがあります。分別は全局事务会话表、分支事务会话表、锁データベース表です。

テーブル作成ステートメントを取得します:https://gitee.com/dhb414/seata/blob/master/script/server/db/mysql.sql#

-- -------------------------------- The script used when storeMode is 'db' --------------------------------
-- the table to store GlobalSession data
CREATE TABLE IF NOT EXISTS `global_table`
(
    `xid`                       VARCHAR(128) NOT NULL,
    `transaction_id`            BIGINT,
    `status`                    TINYINT      NOT NULL,
    `application_id`            VARCHAR(32),
    `transaction_service_group` VARCHAR(32),
    `transaction_name`          VARCHAR(128),
    `timeout`                   INT,
    `begin_time`                BIGINT,
    `application_data`          VARCHAR(2000),
    `gmt_create`                DATETIME,
    `gmt_modified`              DATETIME,
    PRIMARY KEY (`xid`),
    KEY `idx_gmt_modified_status` (`gmt_modified`, `status`),
    KEY `idx_transaction_id` (`transaction_id`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8;

- ブランチセッションデータを保存するテーブル
create not 存在する ` branch_table `

` branch_id ` bigint not null
` xid ` VARCHAR(128) NOT NULL,
`transaction_id` BIGINT,
`resource_group_id` VARCHAR(32),
`resource_id` VARCHAR 256
` branch_type ` varchar 8
` status ` tinyint
` client_id ` varchar 64
` application_data ` varchar 2000
` gmt_create ` datetime 6
` gmt_modified ` >( 6 プライマリ key ` branch_id ` key ` idx_xid ` ` xid ` エンジン = innodb デフォルト charset = utf8 ;



- ロックデータを保存するテーブル
create not 存在する ` lock_table `
(
`row_key` VARCHAR(128) NOT NULL,
`xid` VARCHAR(96),
`transaction_id` BIGINT,
`branch_id` BIGINT NOT NULL,
`resource_id` VARCHAR(256),
`table_name` VARCHAR(32),
`pk` VARCHAR(36),
` gmt_create ` datetime
` gmt_modified ` dateTime
プライマリ key ` row_key `),
KEY ` idx_branch_id ` ` branch_id `)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8;

[外部リンク画像転送に失敗しました。ソースサイトには、アンチリーチングメカニズムがある場合があります。画像を保存して直接アップロードすることをお勧めします(IMG-82K2YAA5-1627345543492)(c:\ users \ java1234 \ desktop \ Deswtop \分散\コースウェア\ Alibaba分散トランザクションフレームワークSeata Courseware.Assets \ Image-20210725083154711.png)]]

すべては一時的なデータであるため、最後のハンド取引は消去される可能性があり、データの確認が必要であり、サービスコードのサイトの起動、デバッグによるキャプチャも必要です。

以下は、Feng 兄弟が収集したデータの一部です。
ここに画像の説明を挿入します

9 NACOS登録センターと構成センターのサポート

Seata は Nacos への注釈サービスをサポートし、また Nacos 構成センターに配置された Seata のすべての配置をサポートし、Nacos 内で一维护;

具体的な手順は次のとおりです。

9.1 项目里追加nacos-client依赖

<dependency>
    <groupId>com.alibaba.nacos</groupId>
    <artifactId>nacos-client</artifactId>
    <version>1.4.0</version>
</dependency>

9.2 集合Nacos注册中心サポート

プロジェクトでapplication.yml登録情報構成を追加

seata:
  registry:
    type: nacos
    nacos:
      application: seata-server
      server-addr: 127.0.0.1:8848
      group : "SEATA_GROUP"
      namespace: ""
      username: "nacos"
      password: "nacos"

Seata-Server構成登録センター

対応する構成センターを registry.conf に追加します。

registry {
    
    
  type = "nacos"

nacos {
application = “ seata-server”
serverAddr = “ 127.0.0.1:8848”
グループ= “SEATA_GROUP”
namespace = “”< /span>}}“”= password “” = username “default”=
cluster




9.3統合されたNACOS構成センターサポート

application.yml 中添加对应的配置中心

seata:
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      group : "SEATA_GROUP"
      namespace: ""
      username: "nacos"
      password: "nacos"

対応する構成センターを registry.conf に追加します。

config {
    
    
  type = "nacos"

nacos {
serverAddr = “127.0.0.1: 8848”
group = “SEATA_GROUP”
namespace = “”
username = “nacos”}< /span>}“nacos”=
password


NACOには認証機能がオンになっていないため、ユーザー名またはパスワードは必要ありません。最終的な構成は次のとおりです。

seata:
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      group: SEATA_GROUP
      namespace: ""
  registry:
    type: nacos
    nacos:
      application: seata-server
      server-addr: 127.0.0.1:8848
      group: "SEATA_GROUP"
      namespace: ""

作为Nacos配置中心,我们需要把seata的一些配置上传到Nacos,配置比较多,官方给了我们一个 config.txt 我们修改后,上传到Nacos。

config.txtダウンロード地址:https://github.com/seata/seata/blob/develop/script/config-center/config.txt

いくつかの変更を加えてみましょう。
[External link image transfer failed. The source site may have an anti-leeching mechanism. It is recommended to save the image and upload it directly (img-83YzokMX-1627345656752) (C:\Users\java1234\Desktop\Distributed Transactions\Courseware \Alibaba 分散トランザクション フレームワーク Seata courseware.assets\image-20210726081430915.png)]

変更したファイルを Seata ディレクトリに置きます。
ここに画像の説明を挿入します

その後、アカウントに提供されている nacos スクリプトを実行し、情報を nacos 制御台に送信します。変更が必要な場合は、制御台を介して直接変更できます。

脚本: https://github.com/seata/seata/blob/develop/script/config-center/nacos-onfig.sh

我们掴 nacos-config.sh 文件放到 conf 目录下

[External link image transfer failed. The source site may have an anti-leeching mechanism. It is recommended to save the image and upload it directly (img-GKNEvfMY-1627345656754) (C:\Users\java1234\Desktop\Distributed Transactions\Courseware \Alibaba 分散トランザクション フレームワーク Seata courseware.assets\image-20210726081723155.png)]

右击鼠标,选Git Bash Here

[外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムが存在する可能性があります。画像を保存して直接アップロードすることをお勧めします (img-Efthw4ZW-1627345656755) (C:\Users\java1234\Desktop\Distributed Transactions\Courseware) \Alibaba 分散トランザクション フレームワーク Seata courseware.assets\image-20210726081823187.png)]

注文を実行します

sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP

[外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムが存在する可能性があります。画像を保存して直接アップロードすることをお勧めします (img-nepS3x1n-1627345656756) (C:\Users\java1234\Desktop\Distributed Transactions\Courseware) \Alibaba 分散トランザクション フレームワーク Seata courseware.assets\image-20210726081952924.png)]

完全なコマンドです:

sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t 0af6e97b-a684-4647-b696-7c6d42aecce7 -u nacos -w nacos

注: コマンド分析: -h -p は nacos のポート アドレスを指定します; -g は設定されたグループを指定します (これが設定されたグループであることに注意してください); -t はネームスペース ID を指定します; -u -w は nacos のユーザー名とパスワードを指定します, similarly, here It only needs to be specified if nacos registration and configuration authentication are enabled.

実行が完了するまで待ちます。
[外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムが存在する可能性があります。画像を保存して直接アップロードすることをお勧めします (img-3AoD40eR-1627345656756) (C:\Users\java1234\Desktop\Distributed Transactions\Courseware) \Alibaba 分散トランザクション フレームワーク Seata courseware.assets\image-20210726082139864.png)]

Nacos 構成センターには Seata の構成があることがわかります。

[外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムが存在する可能性があります。画像を保存して直接アップロードすることをお勧めします (img-JscbU9Il-1627345656757) (C:\Users\java1234\Desktop\Distributed Transactions\Courseware) \Alibaba 分散トランザクション フレームワーク Seata courseware.assets\image-20210726082214229.png)]

このようにして、seata 構成を nacos で維持できます。これは非常に便利です。

9.4 テスト

Seata-server を再起動し、3 つのプロジェクトを再起動し、postman を使用してテストする必要があります。テストは OK です。

10座取引グループ紹介

トランザクションのグループ化とは何ですか?

インスタンス コンポーネントは、サービス サンプルと同様に、seata のリソース グループです。

过事务分组どうやって後端集群に到達しますか?

  1. 最初の手順中構成完了事务分组 (GlobalTransactionScanner 構築メソッドの txServiceGroup パラメータ)
  2. 手順会は、ユーザー構成の構成センターを介して削除service.vgroupMapping .[事务分構成项]、構成项の取得です。 TC 集合群の名前
  3. 集合グループ名プログラムは、一定の前後 + 集合グループ名を介してサービス名を構築し、各構成中心のサービス名は異なります。
  4. サービス名にアクセスし、対応する注釈中心を削除し、対応するサービス名のサービス一覧表を取得し、最終端の真の TC サービス一覧表を取得します

これは何ですか、服务名を直接取得しませんか?

这里多了一层获取事务分组到映射集群的配置。この設計の後、トランザクション グループをリソースの論理分離単位として使用できるようになりました。クラスタ障害が発生した場合、迅速にフェイルオーバーして、対応するグループのみを切り替えることができます。これにより、障害をサービス レベルまで減らすことができますが、前提条件は、 enough server clusters.

11 配套原创Seatavideo教程+ソースコード+文档领取

この投稿を読むのがまだ少し難しい場合は、Feng 兄弟が特別にサポートするソース コード ドキュメントを含む一連のサポート ビデオ チュートリアルを録画しました。
ここに画像の説明を挿入します
ここに画像の説明を挿入します
ビデオ チュートリアルは 1920 年の高解像度です。 *1080 および非 A&V 品質。;
ここに画像の説明を挿入します
ここに画像の説明を挿入します
フェン兄弟のビデオはスタイルが一貫していて、理解しやすく、ナンセンスではなく、全員の時間とエネルギーを無駄にせず、動画を視聴する時間を節約できます。 girls at night!

[seata ビデオ チュートリアル + ドキュメント + ソース コード] が必要な場合は、[java1234] WeChat 公式アカウントをフォローし、[seata] に返信して受け取ってください。
't know how to operate above, you can add Feng Brother WX: [java3459] Receive

感谢csdn

Dian Feng の CSDN ブログを忘れずに [フォロー] してください。

大家好,我是曹尼玛
ここに画像の説明を挿入します
从大学毕业5年,一直努力学习,努力工作,追求新技术,不保守。
ここに画像の説明を挿入します
上个月我来到一家新公司上班,月薪20K,这家公司老板人很好,对员工很关爱,公司氛围不错,同事们也努力把公司项目搞搞好。除了那个混日子的10年开发经验的老王(老板小舅子)
ここに画像の説明を挿入します
由于老板对客户比较负责,业界口碑好,公司的项目越做越大,单子也越来越多,但是很多客户项目要求分布式微服务,因为大部分是金融外贸项目,搞了微服务后,偶尔出现分布式事务不一致性问题,客户很是反感,前段时间,公司用TCC试水,发现这个方案代码侵入性太强,维护也不方便,人工投入太大,也容易编码出错。
ここに画像の説明を挿入します
后来用基于RocketMQ消息队列实现可靠消息最终一致性方案代替,能实现要求,比TCC好维护点,但是实现起来,终究得依赖消息中间件,而且逻辑也有点繁琐,公司项目涉及到得分布式事务模块还是很多的,搞得天罗地网似的。
ここに画像の説明を挿入します
公司急于寻求一种简单快捷高效的低代码侵入式的分布式事务解决方案。
ここに画像の説明を挿入します
作为新技术控,我一直关注新技术,最近2年,阿里分布式事务解决方案Seata很火,人气很足!
ここに画像の説明を挿入します
也深入研究过,现在最新版本1.4.2,基本成熟了,可以商用!作为Spring Cloud Alibaba服务组件,很好集成到项目里,而且我都深入测试过!
So I mustered up the courage and walked directly to my boss's office and asked him to try Seata;
ここに画像の説明を挿入します
My boss is not a conservative person and is willing to try !他说他先研究下Seata。
ここに画像の説明を挿入します
第二天,老板叫我进办公室,直接说“公司的438项目,有一个sb模块涉及分布式事务,你用seata搞下”。我连忙说”OK,没问题,保证完成任务“!
ここに画像の説明を挿入します
由于我对seata比较熟悉,MD笔记整理得井井有条。所以一顿猛操,seata-server配置下,启动,微服务项目applicaton.yml配置下,@GlobalTransactional加上,测试下,没问题,一上午就撸完了,跟老板说”可以让测试部的小姐姐测试下了“。
ここに画像の説明を挿入します
老板惊呆了,这么快就搞完了?半信半疑
ここに画像の説明を挿入します
下午测试部的小姐姐们仔细功能测试,压测,没毛病!偶尔服务调用超时也是自动回滚事务,所以不影响业务,界面有友好用户提示”系统繁忙,请稍后重试“!
ここに画像の説明を挿入します
老板听到测试部的汇报后,直接让版本更新放到线上让客户使用!
用了一个多月,根据客户反馈,以及日志系统查看,这次seata解决方案非常OK!
ここに画像の説明を挿入します
老板让漂亮的小秘把我叫到办公室,然后塞给我一沓厚厚的信封,跟我说 ”曹大哥,明天开始,那个混饭吃胡日子不思进取的10年经验的老王就要滚蛋了,以后技术总监的位置就是你的了,薪资是40K,15薪资+项目奖金+年终奖“,”另外还有特殊福利“,顺便喵看了下旁边芳龄18的小敏秘书!
ここに画像の説明を挿入します
由于我过于激动,那天说话老是合不拢嘴!
ここに画像の説明を挿入します
3年以后,我成为了公司技术一把手,年入百万;
第4年,我当爸爸了,选了个风和日丽的日子,开着保时捷Panamera,带着满月的儿子和小敏一起去拍满月照!
ここに画像の説明を挿入します
ここに画像の説明を挿入します
阿里Seata作为一个优秀得分布式事务解决方案,让穷屌丝的我逆袭了,我决定公开我的seata笔记,顺便还录制了一套Seata视频教程,希望对大家有帮助!

1 アリババの分散トランザクションフレームワーク Seata の紹介

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。 SEATAは、ユーザーにAT、TCC、SAGA、XAトランザクションモードを提供し、ユーザー向けのワンストップ分散ソリューションを作成します。

中文官方站点:https://seata.io/zh-cn/

seata github开源地址:https://github.com/seata

2 分散トランザクションの概要

2.1 地域情勢

コンピュータ システムでは、トランザクションは主にリレーショナル データベースによって制御されます。これは、データベース自体のトランザクション特性を使用することによって実現されるため、データベース トランザクションと呼ばれます。アプリケーションは主にリレーショナル データベースに依存してトランザクションを制御するため、データベースは通常、リレーショナル データベースと組み合わせて使用​​されます。同じサーバーにあるため、リレーショナル データベースに基づくトランザクションはローカル トランザクションとも呼ばれます。

データベース トランザクションの 4 つの主な特徴: ACID

A (アトミック): アトミック性。トランザクションを構成するすべての操作が完了するか、まったく実行されず、部分的に成功したり部分的に失敗したりする可能性はありません。

C (一貫性): 一貫性。データベースの一貫性制約は、トランザクションの実行前後に破棄されません。例: Zhang San が Li Si に 100 元を送金し、送金前後のデータは正しいです。これを一貫性と呼びます。Zhang San が 100 元を送金しても、Li Si の口座が 100 元増えなかった場合、データエラーです。整合性が取れません。

I (分離): 分離。データベース内のトランザクションは通常、同時実行されます。分離とは、2 つの同時トランザクションの実行が互いに干渉しないことを意味します。1 つのトランザクションは実行できません。実行中の他のトランザクションの中間状態。トランザクション分離レベルを構成すると、ダーティ リードや繰り返し読み取りを回避できます。

D (耐久性): 耐久性。トランザクションの完了後、トランザクションによって行われたデータへの変更はデータベースに保持され、ロールバックされません。

データベース トランザクションが実装されると、トランザクションのすべての操作が分割不可能な実行ユニットに組み込まれます。この実行ユニットのすべての操作は成功するか失敗します。操作のいずれか 1 つが実行に失敗すると、全体の操作が失敗します。トランザクションは失敗します。ロールバックします。

2.2 分散トランザクション

インターネットの急速な発展に伴い、ソフトウェア システムは元の単一アプリケーションから分散アプリケーションに変わりました。

分散システムでは、アプリケーション システムが独立して展開できる複数のサービスに分割されます。そのため、トランザクション操作を完了するには、サービス間のリモート コラボレーションが必要です。この分散システム環境は、さまざまなサービスで構成されています。トランザクションは、複数のリモート コラボレーションを通じて完了します。このネットワークは分散トランザクションと呼ばれ、ユーザー登録やボーナスポイントトランザクション、注文在庫削減トランザクションの作成、銀行振込トランザクションなどです。分散トランザクション。

3 SpringCloud Alibaba 分散基本ケースの構築

単純な注文ビジネスをシミュレートします。クライアントが REST 外部サービスを呼び出し、REST サービスが注文サービスを呼び出して注文を作成し、アカウント サービスを呼び出して口座引き落とし操作を実現し、最終的に注文ビジネスを完了します。

2.1 ケースアーキテクチャ設計

すべてのサービスは、偽りのリモート呼び出しを容易にするために nacos に登録されています。注文サービスとアカウント サービスにはそれぞれ独立したデータベースがあります。アーキテクチャ設計は次のとおりです。
ここに画像の説明を挿入します

プロジェクト全体の構造は次のとおりです。
ここに画像の説明を挿入します

seatatestこれは親プロジェクトであり、主に依存関係の管理、依存関係のバージョン管理を行い、すべてのサブモジュール プロジェクトを管理します。

seata-commonサブプロジェクトは主に、他のサブプロジェクトが必要とするパブリック依存関係、およびパブリック エンティティ、ツール クラス、構成クラスの統合カプセル化を導入します。

seata-orderサブプロジェクトは主に注文サービスを提供し、注文を生成します。

seata-accountサブプロジェクトは主に口座サービスを提供し、注文に基づいてお金を引き落とします。

seata-webサブプロジェクトは主にクライアントの注文リクエストを処理し、リモートで注文を呼び出すふりをし、アカウント サービス インターフェイスを処理し、最終的に注文処理を完了します。

2.2 データベース設計

db_order (注文データベース)、db_account (アカウント データベース)、 という 2 つの新しいデータベースを作成します。

db_orderデータベースに新しいテーブルを作成するt_orderテーブルの順序:

CREATE TABLE `t_order` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `orderNo` varchar(100) DEFAULT NULL,
  `userId` int(11) DEFAULT NULL,
  `count` int(11) DEFAULT NULL,
  `amount` int(11) DEFAULT NULL,
  `remark` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8

db_accountデータベースに新しいテーブルを作成するt_accountユーザー アカウント テーブル:

CREATE TABLE `t_account` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `userId` int(11) DEFAULT NULL,
  `balance` int(11) DEFAULT NULL,
  `remark` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8

データを挿入します:

insert into `t_account` (`id`, `userId`, `balance`, `remark`) values('1','1','2000','jack的账户');
insert into `t_account` (`id`, `userId`, `balance`, `remark`) values('2','2','1000','marry的账户');

2.3 最も重要な親プロジェクトの構築

Seatatest は親プロジェクトで、主に依存関係の管理、依存関係のバージョン管理を行い、すべてのサブモジュール プロジェクトを管理します。

そのpackagingタイプはであることに注意してください。pom

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.java1234</groupId>
    <artifactId>seatatest</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>seata-common</module>
        <module>seata-order</module>
        <module>seata-account</module>
        <module>seata-web</module>
    </modules>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <druid.version>1.1.10</druid.version>
        <spring-cloud.version>Hoxton.SR8</spring-cloud.version>
        <springboot.version>2.3.2.RELEASE</springboot.version>
        <springcloudalibaba.version>2.2.4.RELEASE</springcloudalibaba.version>
        <fastjson.version>1.2.35</fastjson.version>
        <commons-lang3.version>3.6</commons-lang3.version>
        <seata-common.version>1.0-SNAPSHOT</seata-common.version>
        <mybatis.version>2.1.0</mybatis.version>
    </properties>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${springboot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${springcloudalibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- 连接池 -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>${druid.version}</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId><artifactId>fastjson</artifactId> <version>${fastjson.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
                <version>${commons-lang3.version}</version>
            </dependency>
            <dependency>
                <groupId>com.java1234</groupId>
                <artifactId>seata-common</artifactId>
                <version>${seata-common.version}</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

2.4 シータ共通サブプロジェクト建設

seata-commonサブプロジェクトは主に、他のサブプロジェクトが必要とするパブリック依存関係、およびパブリック エンティティ、ツール クラス、構成クラスの統合カプセル化を導入します。

プロジェクトの構造:
ここに画像の説明を挿入します

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>seatatest</artifactId>
        <groupId>com.java1234</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>seata-common<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependencies</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.boot<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-boot-starter-web<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.boot<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-boot-starter-test<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>scope</span><span class="token punctuation">&gt;</span></span>test<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>scope</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>

    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>com.alibaba.cloud<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-cloud-starter-alibaba-nacos-discovery<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>com.alibaba.cloud<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-cloud-starter-alibaba-nacos-config<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.boot<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-boot-devtools<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>scope</span><span class="token punctuation">&gt;</span></span>runtime<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>scope</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>optional</span><span class="token punctuation">&gt;</span></span>true<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>optional</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>mysql<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>mysql-connector-java<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>scope</span><span class="token punctuation">&gt;</span></span>runtime<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>scope</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.projectlombok<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>lombok<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.boot<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-boot-starter-test<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>scope</span><span class="token punctuation">&gt;</span></span>test<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>scope</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.mybatis.spring.boot<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>mybatis-spring-boot-starter<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>com.alibaba<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>druid<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token comment">&lt;!-- spring boot redis 缓存引入 --&gt;</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.boot<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-boot-starter-data-redis<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token comment">&lt;!-- lettuce pool 缓存连接池 --&gt;</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.apache.commons<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>commons-pool2<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>com.alibaba<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>fastjson<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>commons-codec<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>commons-codec<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.apache.commons<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>commons-lang3<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>




<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependencies</span><span class="token punctuation">&gt;</span></span>

おすすめ

転載: blog.csdn.net/fujiakai/article/details/123500670