惠州做网站首选惠州邦,网站建设公司兴田德润专业,不懂编程如何做网站,装修顺序XA协议:是一种标准协议#xff0c;允许事务管理器协调多个资源管理器#xff0c;确保在分布式事务中的一致性和原子性。
JTA:是JavaEE规范中的一种#xff0c;用于管理分布式事务的 API#xff0c;提供了事务的控制和协调机制
Atomikos理解成JTA的实现
XA是JTA的基础(JT…XA协议:是一种标准协议允许事务管理器协调多个资源管理器确保在分布式事务中的一致性和原子性。
JTA:是JavaEE规范中的一种用于管理分布式事务的 API提供了事务的控制和协调机制
Atomikos理解成JTA的实现
XA是JTA的基础(JTA实现了XA协议) Atomikos实现了JTA
Atomikos这种方式限定与单应用多数据源使用场景. 关于理论的一些:
当业务操作需要涉及到多个数据库时,这就可称为分布式事务处理.实现分布式事务处理的关键是采用一种手段保证事务涉及的所有数据库所做的全部动作要么全部生效,要买么全部回滚.
目前处理分布式事务的规范就是XA规范.
X/Open组织为分布式事务制定了的事务中间件与数据库之间的接口规范.这种规范就是XA规范.事务中间件用它来通知数据库事务开始,提交,回滚等
X/Open组织仅仅制定了分布式事务处理的XA规范,但具体的实现则由不同的数据库厂商自行提供.
对于大部分主流商业及开源数据库都提供了XA规范的驱动 分布式事务处理方法很多 XA 方案 2PC 两阶段提交: 2PC 的传统方案是在数据库层面实现的如 Oracle 、 MySQL 都支持 2PC 协议为了统一标准减少行业内不必要的对 接成本需要制定标准化的处理模型及接口标准国际开放标准组织 Open Group 定义了分布式事务处理模型 DTP Distributed Transaction Processing Reference Model 。 成功示例: 失败示例: 执行流程如下 1 、应用程序 AP 持有用户库和积分库两个数据源。 2 、应用程序 AP 通过 TM 通知用户库 RM 新增用户同时通知积分库 RM 为该用户新增积分 RM 此时并未提交事 务此时用户和积分资源锁定。 3 、 TM 收到执行回复只要有一方失败则分别向其他 RM 发起回滚事务回滚完毕资源锁释放。 4 、 TM 收到执行回复全部成功此时向所有 RM 发起提交事务提交完毕资源锁释放。 DTP 模型定义如下角色 AP (Application Program) 即应用程序可以理解为使用 DTP 分布式事务的程序。 RM (Resource Manager) 即资源管理器可以理解为事务的参与者一般情况下是指一个数据库实例通过 资源管理器对该数据库进行控制资源管理器控制着分支事务。 TM (Transaction Manager) 事务管理器负责协调和管理事务事务管理器控制着全局事务管理事务生命 周期并协调各个 RM 。 全局事务 是指分布式事务处理环境中需要操作多个数据库共同完成一个工作这个 工作即是一个全局事务。 DTP 模型定义 TM 和 RM 之间通讯的接口规范叫 XA 简单理解为数据库提供的 2PC 接口协议 基于数据库的 XA 协议来实现 2PC 又称为 XA 方案 。 以上三个角色之间的交互方式如下 1 TM 向 AP 提供 应用程序编程接口 AP 通过 TM 提交及回滚事务。 2 TM 交易中间件通过 XA 接口来通知 RM 数据库事务的开始、结束以及提交、回滚等。 总结 整个 2PC 的事务流程涉及到三个角色 AP 、 RM 、 TM 。 AP 指的是使用 2PC 分布式事务的应用程序 RM 指的是资 源管理器它控制着分支事务 TM 指的是事务管理器它控制着整个全局事务。 1 在 准备阶段 RM 执行实际的业务操作但不提交事务资源锁定 2 在 提交阶段 TM 会接受 RM 在准备阶段的执行回复只要有任一个 RM 执行失败 TM 会通知所有 RM 执行回滚操 作否则 TM 将会通知所有 RM 提交该事务。提交阶段结束资源锁释放。 XA 方案的问题 1 、需要本地数据库支持 XA 协议。 2 、资源锁需要等到两个阶段结束才释放性能较差。(这句话掠过哈,这句话是讲seata的人说的 当然 也许 可能没有阿里的 seata好用) 下面是SpringBootMybatis多数据源配置 项目结构 这边随意建了两张表测试 分别在不同数据库 CREATE TABLE news ( id int NOT NULL AUTO_INCREMENT, title varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, content varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, PRIMARY KEY (id) ) ENGINEInnoDB AUTO_INCREMENT14 DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_unicode_ci; CREATE TABLE user_inf ( user_id int NOT NULL AUTO_INCREMENT, name varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, password varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, age int DEFAULT NULL, PRIMARY KEY (user_id) ) ENGINEInnoDB AUTO_INCREMENT7 DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_unicode_ci; application.properties 两个数据源配置文件 Configuration
MapperScan(basePackages {com.example.demo5.mapper},sqlSessionFactoryRef primarySqlSessionFactory)
public class DataSourceConfig1 {PrimaryBean(nameprimaryDataSource)ConfigurationProperties(prefix spring.datasource.primary)public DataSource primaryDataSource(){//return DataSourceBuilder.create().build();//return new HikariDataSource();return new DruidDataSource();}PrimaryBean(nameprimarySqlSessionFactory)public SqlSessionFactory primarySqlSessionFactory(Qualifier(primaryDataSource) DataSource dataSource) throws Exception {SqlSessionFactoryBean beannew SqlSessionFactoryBean();bean.setDataSource(dataSource);bean.setTypeAliasesPackage(com.example.demo5.pojo);bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(classpath:mappers/*Mapper.xml));SqlSessionFactory sqlSessionFactory bean.getObject();sqlSessionFactory.getConfiguration().setMapUnderscoreToCamelCase(true);//sqlSessionFactory.getConfiguration().setJdbcTypeForNull(JdbcType.NULL);return sqlSessionFactory;}PrimaryBean(nameprimarySqlSessionTemplate)public SqlSessionTemplate primarySqlSessionTemplate(Qualifier(primarySqlSessionFactory)SqlSessionFactory sqlSessionFactory){return new SqlSessionTemplate(sqlSessionFactory);}PrimaryBean(nameprimaryJdbcTemplate)public JdbcTemplate primaryJdbcTemplate(Qualifier(primaryDataSource)DataSource dataSource){return new JdbcTemplate(dataSource);}PrimaryBean(nameprimaryTransactionManager)public DataSourceTransactionManager primaryTransactionManager(Qualifier(primaryDataSource)DataSource dataSource){return new DataSourceTransactionManager(dataSource);}} Configuration
MapperScan(basePackages {com.example.demo5.mapper2},sqlSessionFactoryRef secondSqlSessionFactory)
public class DataSourceConfig2 {Bean(namesecondDataSource)ConfigurationProperties(prefix spring.datasource.second)public DataSource secondDataSource(){return DataSourceBuilder.create().build();}Bean(namesecondSqlSessionFactory)public SqlSessionFactory secondSqlSessionFactory(Qualifier(secondDataSource) DataSource dataSource) throws Exception {SqlSessionFactoryBean beannew SqlSessionFactoryBean();bean.setDataSource(dataSource);bean.setTypeAliasesPackage(com.example.demo5.pojo2);bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(classpath:mappers2/*Mapper.xml));SqlSessionFactory sqlSessionFactory bean.getObject();sqlSessionFactory.getConfiguration().setMapUnderscoreToCamelCase(true);//sqlSessionFactory.getConfiguration().setJdbcTypeForNull(JdbcType.NULL);return sqlSessionFactory;}Bean(namesecondSqlSessionTemplate)public SqlSessionTemplate secondSqlSessionTemplate(Qualifier(secondSqlSessionFactory)SqlSessionFactory sqlSessionFactory){return new SqlSessionTemplate(sqlSessionFactory);}Bean(namesecondJdbcTemplate)public JdbcTemplate secondJdbcTemplate(Qualifier(secondDataSource)DataSource dataSource){return new JdbcTemplate(dataSource);}Bean(namesecondTransactionManager)public DataSourceTransactionManager secondTransactionManager(Qualifier(secondDataSource)DataSource dataSource){return new DataSourceTransactionManager(dataSource);}
} 实体类 service serviceImpl 事务测试 但是这两个事务管理器无法满足分布式事务 就是说我要将A数据库和B数据库的操作放在一个事务中,无法满足 Atomikos的使用 添加SpringBoot整合Atomikos的starter的jar包 Atomikos的数据源必须是AtomikosDataSourceBean,因此配置的数据源必须是XADatasource 然后再使用AtomikosDataSourceBean包装它们 使用Atomikos Atomikos的数据源必须是AtomikosDataSourceBean,因此配置数据源必须先使用XADatasource, 然后再使用AtomikosDataSourceBean包装他们. 将不同数据源对应的AtomikosDataSourceBean注入对应sqlSessionFactory application.properties 两个配置文件 Configuration
MapperScan(basePackages {com.example.demo5.mapper},sqlSessionFactoryRef primarySqlSessionFactory)
public class DataSourceConfig1 {// PrimaryBean(nameprimary)ConfigurationProperties(prefix spring.datasource.primary)public XADataSource primary(){//MysqlXADataSource mysqlXADataSource new MysqlXADataSource();//application.properties中的要与他里面的属性对应//return mysqlXADataSource;DruidXADataSource druidXADataSourcenew DruidXADataSource();return druidXADataSource;}Bean(nameprimaryDataSource)Primarypublic DataSource primaryDataSource(){AtomikosDataSourceBean atomikosDataSourceBeannew AtomikosDataSourceBean();atomikosDataSourceBean.setXaDataSource(primary());atomikosDataSourceBean.setMaxPoolSize(20);atomikosDataSourceBean.setUniqueResourceName(mysqlDs1);//取个唯一名字return atomikosDataSourceBean;}PrimaryBean(nameprimarySqlSessionFactory)public SqlSessionFactory primarySqlSessionFactory(Qualifier(primaryDataSource) DataSource dataSource) throws Exception {SqlSessionFactoryBean beannew SqlSessionFactoryBean();bean.setDataSource(dataSource);bean.setTypeAliasesPackage(com.example.demo5.pojo);bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(classpath:mappers/*Mapper.xml));SqlSessionFactory sqlSessionFactory bean.getObject();sqlSessionFactory.getConfiguration().setMapUnderscoreToCamelCase(true);//sqlSessionFactory.getConfiguration().setJdbcTypeForNull(JdbcType.NULL);return sqlSessionFactory;}PrimaryBean(nameprimarySqlSessionTemplate)public SqlSessionTemplate primarySqlSessionTemplate(Qualifier(primarySqlSessionFactory)SqlSessionFactory sqlSessionFactory){return new SqlSessionTemplate(sqlSessionFactory);}PrimaryBean(nameprimaryJdbcTemplate)public JdbcTemplate primaryJdbcTemplate(Qualifier(primaryDataSource)DataSource dataSource){return new JdbcTemplate(dataSource);}//使用JTA全局事务管理器后,不要再自定义事务管理器
// Primary
// Bean(nameprimaryTransactionManager)
// public DataSourceTransactionManager primaryTransactionManager(Qualifier(primaryDataSource)DataSource dataSource){
// return new DataSourceTransactionManager(dataSource);
// }} Configuration
MapperScan(basePackages {com.example.demo5.mapper2},sqlSessionFactoryRef secondSqlSessionFactory)
public class DataSourceConfig2 {// PrimaryBean(namesecond)ConfigurationProperties(prefix spring.datasource.second)public XADataSource second(){
// MysqlXADataSource mysqlXADataSource new MysqlXADataSource();//application.properties中的要与他里面的属性对应
//
// return mysqlXADataSource;DruidXADataSource druidXADataSourcenew DruidXADataSource();return druidXADataSource;}Bean(namesecondDataSource)public DataSource secondDataSource(){AtomikosDataSourceBean atomikosDataSourceBeannew AtomikosDataSourceBean();atomikosDataSourceBean.setXaDataSource(second());atomikosDataSourceBean.setMaxPoolSize(20);atomikosDataSourceBean.setUniqueResourceName(mysqlDs2);//取个唯一名字return atomikosDataSourceBean;}Bean(namesecondSqlSessionFactory)public SqlSessionFactory secondSqlSessionFactory(Qualifier(secondDataSource) DataSource dataSource) throws Exception {SqlSessionFactoryBean beannew SqlSessionFactoryBean();bean.setDataSource(dataSource);bean.setTypeAliasesPackage(com.example.demo5.pojo2);bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(classpath:mappers2/*Mapper.xml));SqlSessionFactory sqlSessionFactory bean.getObject();sqlSessionFactory.getConfiguration().setMapUnderscoreToCamelCase(true);//sqlSessionFactory.getConfiguration().setJdbcTypeForNull(JdbcType.NULL);return sqlSessionFactory;}Bean(namesecondSqlSessionTemplate)public SqlSessionTemplate secondSqlSessionTemplate(Qualifier(secondSqlSessionFactory)SqlSessionFactory sqlSessionFactory){return new SqlSessionTemplate(sqlSessionFactory);}Bean(namesecondJdbcTemplate)public JdbcTemplate secondJdbcTemplate(Qualifier(secondDataSource)DataSource dataSource){return new JdbcTemplate(dataSource);}// Bean(namesecondTransactionManager)
// public DataSourceTransactionManager secondTransactionManager(Qualifier(secondDataSource)DataSource dataSource){
// return new DataSourceTransactionManager(dataSource);
// }
} dependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactIdversion2.3.0/version/dependency!--stomikos--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-jta-atomikos/artifactId/dependency!--德鲁伊--dependencygroupIdcom.alibaba/groupIdartifactIddruid-spring-boot-starter/artifactIdversion1.2.15/version/dependencydependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactId
!-- scoperuntime/scope使用MysqlXADataSource的话把运行时去掉,不然找不到 不用可以恢复运行时--/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependencydependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter-test/artifactIdversion3.0.2/versionscopetest/scope/dependency/dependenciesbuildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactIdconfigurationexcludesexcludegroupIdorg.projectlombok/groupIdartifactIdlombok/artifactId/exclude/excludes/configuration/plugin/plugins/build