実際のプロジェクトでは、分散トランザクションを避けるように努めます。 ただし、場合によってはサービスを分割する必要があり、分散トランザクションの問題が発生することがあります。
同時に、分散取引では面接で市場についても質問されるので、このケースで練習して、面接で 123 について話すことができます。
ここはビジネス上の問題です。ユーザーがクーポンを受け取ると、ユーザーがクーポンを受け取った回数を差し引く必要があり、その後、ユーザーがクーポンを受け取った記録が作成されます。記録された。


Amitikos を導入しました。
分散トランザクション
分散トランザクションは、複数のコンピュータまたはデータベースにまたがるトランザクションを指します。ネットワークの遅延、障害、またはこれらのコンピュータまたはデータベース間の不一致が考えられます。分散トランザクションでは、データの正確性と整合性を確保するために、すべての操作の原子性、一貫性、分離性、耐久性を確保する必要があります。
#分散トランザクション プロトコルとは何ですか? 分散トランザクション プロトコルには、2PC (2 フェーズ コミット) と 3PC (3 フェーズ コミット) の 2 つの主なタイプがあります。
2PC は現在最も一般的に使用されている分散トランザクション プロトコルであり、そのプロセスは準備段階と送信段階の 2 つの段階に分かれています。準備フェーズでは、トランザクション コーディネーターがすべての参加者に準備リクエストを発行し、参加者はローカル トランザクションを実行して準備状態にし、準備結果をトランザクション コーディネーターに返します。コミット フェーズでは、すべての参加者が正常に実行された場合、トランザクション コーディネーターはすべての参加者にコミット リクエストを発行し、参加者はローカル トランザクションをコミットします。それ以外の場合、トランザクション コーディネーターはすべての参加者にロールバック リクエストを発行し、参加者はローカル トランザクションをロールバックします。取引のロールです。
3PC は 2PC の改良版で、2PC に基づいて準備と提出の段階が追加されています。送信準備フェーズでは、コーディネーターが参加者に送信できるかどうかを尋ねます。参加者が同意を返した場合は送信フェーズで直接送信され、そうでない場合は送信フェーズでロールバックされます。
分散トランザクション ソリューションの実装ソリューションには次のものが含まれます。
- メッセージ キューに基づく分散トランザクション ソリューション (RocketMQ のオープン ソース ソリューションなど)
- 分散トランザクション フレームワーク (Seata、TCC-Transaction、その他のフレームワークなど) に基づく分散トランザクション ソリューション
- XA プロトコルに基づく分散トランザクション ソリューション (例: JTA など) #信頼性の高いメッセージの結果整合性に基づく分散トランザクション ソリューション (Alibaba の分散トランザクション ミドルウェア GTS など)
- # #分散トランザクション スキームCAP 原則に基づく (CQRS アーキテクチャのイベント ソーシング モードなど)
トランザクション マネージャー インターフェイス
javax.transaction.TransactionManager
。これは、トランザクションの開始、送信、引き出し、およびその他の操作を定義します。XA 仕様を満たすリソース定義インターフェイス
javax.transaction.xa.XAResource
XAResourceInterface を作成し、このインターフェイスで定義された 2 フェーズ送信関連のインターフェイスを実装します。
JTA インターフェースを使用してトランザクションを実装するアプリケーションがある場合、アプリケーションの実行中には、JTA を実装するコンテナーが必要になります。通常、これは JBoss、Websphere、その他のアプリケーション サーバーなどの J2EE コンテナーです。
ただし、JTA を実装する独立したフレームワークもいくつかあります。たとえば、Amitikos や bitronix は JTA 実装フレームワークを jar パッケージの形式で提供しています。このようにして、JTA を使用して Tomcat や Jetty などのサーバー上でトランザクションを実装するアプリケーション システムを実行できます。
上記のローカル トランザクションと外部トランザクションの違いで述べたように、JTA トランザクションは外部トランザクションであり、複数のリソースのトランザクション性を実装するために使用できます。各リソースによって実装された XAResource
を通じて、2 フェーズの送信を正確に制御します。興味のある学生は、このインターフェースのメソッドを見てみることができます。コミット、ロールバックなどのメソッドに加えて、end()
、forget()
、isSameRM もあります。 ()
、prepare()
など。これらのインターフェイスだけから、2 フェーズ トランザクションの実装における JTA の複雑さが想像できます。
XA とは何ですか?
XA は、X/Open 組織によって提案された分散トランザクション アーキテクチャ (またはプロトコル) です。 XA アーキテクチャは主に、(グローバル) トランザクション マネージャーと (ローカル) リソース マネージャー間のインターフェイスを定義します。 XA インターフェイスは、トランザクション マネージャーと 1 つ以上のリソース マネージャー間の通信ブリッジを形成する双方向システム インターフェイスです。つまり、XAに基づくトランザクションでは、システムが複数のデータベースにアクセスしたり、データベースとメッセージミドルウェアなどのリソースの両方にアクセスしたりするなど、複数のリソースに対するトランザクション管理が可能となります。このようにして、送信されたすべてのトランザクションまたはキャンセルされたすべてのトランザクションを複数のデータベースおよびメッセージ ミドルウェアに直接実装できます。 XA仕様はJava仕様ではなく汎用仕様であり、現在、さまざまなデータベースや多くのメッセージミドルウェアがXA仕様をサポートしています。
JTA は XA 仕様を満たす仕様であり、Java 開発に使用されます。したがって、JTA を使用して分散トランザクションを実装すると言うとき、実際には、JTA 仕様を使用して、システム内の複数のデータベース、メッセージ ミドルウェア、およびその他のリソースとのトランザクションを実装することを意味します。
Amitikos とは
Atomikos は非常に人気のあるオープンソース トランザクション マネージャーであり、Spring Boot アプリケーションに組み込むことができます。 Tomcat アプリケーション サーバーは JTA 仕様を実装していません。Tomcat をアプリケーション サーバーとして使用する場合は、サードパーティのトランザクション マネージャー クラスをグローバル トランザクション マネージャーとして使用する必要があります。これを行うのは Amitikos フレームワークであり、トランザクション管理をアプリケーションに統合します。アプリケーションサーバーに依存しません。
Spring Boot は Atomikos を統合します
たくさんの理論について話すのは無駄です。コードを見せてください。
テクノロジー スタック:Spring Boot MyBatis Atomikos MySQL
この記事のコードに従う場合は、mysql のバージョンに注意してください。
最初に 2 つのデータベース (my-db_0 と my-db_1) を構築し、次に各データベースにテーブルを作成します。
データベース my-db_0 内:
CREATE TABLE `t_user_0` ( `id` bigint NOT NULL AUTO_INCREMENT, `user_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `age` int NOT NULL, `gender` int NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8;
データベース my-db_1 内:
CREATE TABLE `t_user_1` ( `id` bigint NOT NULL AUTO_INCREMENT, `user_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `age` int NOT NULL, `gender` int NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8;
これは分散トランザクションを説明するためだけのものであり、テーブル。

# #maven 設定
プロパティ設定
データ ソース
MyBatis Scan("classpath*:com/tian/mapper/user1/*.xml")
もう 1 つは基本的に同じです。つまり、スキャンパスが次のように変更されます。 mapper.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.tian.mapper.user0.User0Mapper">
<!-- -->
<cache eviction="LRU" flushInterval="10000" size="1024" />
<resultMap id="BaseResultMap" type="com.tian.entity.User0">
<id column="id" jdbcType="BIGINT" property="id" />
<result column="user_name" jdbcType="VARCHAR" property="userName" />
<result column="age" jdbcType="INTEGER" property="age" />
<result column="gender" jdbcType="INTEGER" property="gender" />
</resultMap>
<sql id="Base_Column_List">
id, user_name, age, gender
</sql>
<insert id="insert" parameterType="com.tian.entity.User0">
insert into t_user_0 (id, user_name,age, gender)
values (#{id,jdbcType=BIGINT}, #{userName,jdbcType=VARCHAR},#{age,jdbcType=INTEGER},#{gender,jdbcType=INTEGER})
</insert>
</mapper>
対応するマッパー インターフェイスも非常にシンプルです。以下にその 1 つを示します: public interface User0Mapper { int insert(User0 record); }service
/**
* @author tianwc 公众号:java后端技术全栈、面试专栏
* @version 1.0.0
* @date 2023年05月11日 19:38
* 博客地址:<a href="http://woaijava.cc/">博客地址</a>
* <p>
* 模拟三种场景:正常、制造异常、数据库异常
*/
@Service
public class UserServiceImpl implements UserService {
@Resource
private User0Mapper user0Mapper;
@Resource
private User1Mapper user1Mapper;
/**
* 正常逻辑 同时对两个数据库进行 插入数据
*/
@Transactional
@Override
public int transaction1() throws Exception {
User1 user1 = new User1();
user1.setUserName("22222");
user1.setAge(11);
user1.setGender(0);
user1Mapper.add(user1);
System.out.println("---------------------------");
// sit(数据源1)
User0 user0 = new User0();
user0.setUserName("111111");
user0.setAge(11);
user0.setGender(0);
user0Mapper.insert(user0);
return 1;
}
/**
* 正常逻辑 同时对两个数据库进行 插入数据
* 数据插入完后 出现异常
*/
@Transactional
@Override
public int transaction2() throws Exception {
User1 user1 = new User1();
user1.setUserName("22222");
user1.setAge(11);
user1.setGender(0);
user1Mapper.add(user1);
System.out.println("---------------------------");
// sit(数据源1)
User0 user0 = new User0();
user0.setUserName("111111");
user0.setAge(11);
user0.setGender(0);
user0Mapper.insert(user0);
//认为制造一个异常
int a=1/0;
return 1;
}
/**
* 第一个数据插入成功 第二个数据插入失败
*/
@Transactional
@Override
public int transaction3() throws Exception {
User1 user1 = new User1();
user1.setUserName("22222");
user1.setAge(11);
user1.setGender(0);
user1Mapper.add(user1);
System.out.println("---------------------------");
// sit(数据源1)
User0 user0 = new User0();
//故意搞长点,模拟插入失败 让前面的数据回滚 user0.setUserName("111110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001");
user0.setAge(11);
user0.setGender(0);
user0Mapper.insert(user0);
return 1;
}
}
コントローラー ##
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; /** * @author tianwc 公众号:java后端技术全栈、面试专栏 * @version 1.0.0 * @date 2023年05月11日 19:38 * 博客地址:<a href="http://woaijava.cc/">博客地址</a> * <p> * 项目启动类 */ @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) //@ComponentScan(basePackages = {"com.tian"}) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
プロジェクトを開始し、次の 3 つをそれぞれテストします:
http://localhost:9001/user/test2 結果: 両方のデータベースに、新しいテーブル データが作成されます。
結果: 除数をゼロにすることはできないという例外がスローされ、新しいデータはどちらのデータベースにも追加されません。
http://localhost:9001/user/test3
結果: データ フィールド値が長すぎる例外がスローされ、新しいデータはどちらのデータベースにも追加されません。
以上がSpring Boot + MyBatis + Atomikos + MySQL (ソースコード付き)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

本篇文章给大家带来了关于mysql的相关知识,其中主要介绍了关于架构原理的相关内容,MySQL Server架构自顶向下大致可以分网络连接层、服务层、存储引擎层和系统文件层,下面一起来看一下,希望对大家有帮助。

mysql的msi与zip版本的区别:1、zip包含的安装程序是一种主动安装,而msi包含的是被installer所用的安装文件以提交请求的方式安装;2、zip是一种数据压缩和文档存储的文件格式,msi是微软格式的安装包。

方法:1、利用right函数,语法为“update 表名 set 指定字段 = right(指定字段, length(指定字段)-1)...”;2、利用substring函数,语法为“select substring(指定字段,2)..”。

在mysql中,可以利用char()和REPLACE()函数来替换换行符;REPLACE()函数可以用新字符串替换列中的换行符,而换行符可使用“char(13)”来表示,语法为“replace(字段名,char(13),'新字符串') ”。

转换方法:1、利用cast函数,语法“select * from 表名 order by cast(字段名 as SIGNED)”;2、利用“select * from 表名 order by CONVERT(字段名,SIGNED)”语句。

本篇文章给大家带来了关于mysql的相关知识,其中主要介绍了关于MySQL复制技术的相关问题,包括了异步复制、半同步复制等等内容,下面一起来看一下,希望对大家有帮助。

在mysql中,可以利用REGEXP运算符判断数据是否是数字类型,语法为“String REGEXP '[^0-9.]'”;该运算符是正则表达式的缩写,若数据字符中含有数字时,返回的结果是true,反之返回的结果是false。

本篇文章给大家带来了关于mysql的相关知识,其中主要介绍了mysql高级篇的一些问题,包括了索引是什么、索引底层实现等等问题,下面一起来看一下,希望对大家有帮助。


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

SublimeText3 英語版
推奨: Win バージョン、コードプロンプトをサポート!

SecLists
SecLists は、セキュリティ テスターの究極の相棒です。これは、セキュリティ評価中に頻繁に使用されるさまざまな種類のリストを 1 か所にまとめたものです。 SecLists は、セキュリティ テスターが必要とする可能性のあるすべてのリストを便利に提供することで、セキュリティ テストをより効率的かつ生産的にするのに役立ちます。リストの種類には、ユーザー名、パスワード、URL、ファジング ペイロード、機密データ パターン、Web シェルなどが含まれます。テスターはこのリポジトリを新しいテスト マシンにプルするだけで、必要なあらゆる種類のリストにアクセスできるようになります。

Dreamweaver Mac版
ビジュアル Web 開発ツール

SAP NetWeaver Server Adapter for Eclipse
Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

SublimeText3 Linux 新バージョン
SublimeText3 Linux 最新バージョン

ホットトピック



