分布式事务-基于XA协议的两阶段提交

分布式事务-基于XA协议的两阶段提交

XA协议是由X/OPen组织提出的分布式规范,mysql5.7以上版本均支持XA协议

由一个事务管理器(TM)和多个资源管理器组成(RM)

提交分为两个阶段 prepare和commit,保证事务的强一致性

缺点:效率比较低 比本地事务的相差10倍以上

在config中配置两个XA数据源,配置@MapperScan扫描不同的包

// ConfigDB1
@Configuration
@MapperScan(value = "com.alex.demo.db1.dao", sqlSessionFactoryRef = "db1SqlSessionFactoryBean")
public class ConfigDB1 {

    @Bean("db1DataSource")
    public DataSource db1DataSource(){
        // 使用基于XA协议的Atomikos数据源 mysql5.7和8.0 以上的版本都支持
        MysqlXADataSource xaDataSource = new MysqlXADataSource();
        xaDataSource.setUser("root");
        xaDataSource.setPassword("123456");
        xaDataSource.setUrl("jdbc:mysql://192.168.1.4:3310/xa");
        AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
        atomikosDataSourceBean.setXaDataSource(xaDataSource);
        return atomikosDataSourceBean;
    }

    @Bean("db1SqlSessionFactoryBean")
    public SqlSessionFactoryBean sqlSessionFactoryBean(@Qualifier("db1DataSource") DataSource dataSource) throws IOException {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
        sqlSessionFactoryBean.setMapperLocations(resourceResolver.getResources("mybatis/db1/*.xml"));
        return sqlSessionFactoryBean;
    }
}

//ConfigDB2
@Configuration
@MapperScan(value = "com.alex.demo.db2.dao",sqlSessionFactoryRef = "db2SqlSessionFactoryBean")
public class ConfigDB2 {

    @Bean("db2DataSource")
    public DataSource db2DataSource(){
        // 使用基于XA协议的Atomikos数据源 mysql5.78.0 以上的版本都支持
        MysqlXADataSource xaDataSource = new MysqlXADataSource();
        xaDataSource.setUser("root");
        xaDataSource.setPassword("123456");
        xaDataSource.setUrl("jdbc:mysql://192.168.1.4:3310/xa");
        AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
        atomikosDataSourceBean.setXaDataSource(xaDataSource);
        return atomikosDataSourceBean;
    }

    @Bean("db2SqlSessionFactoryBean")
    public SqlSessionFactoryBean sqlSessionFactoryBean(@Qualifier("db2DataSource") DataSource dataSource) throws IOException {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
        sqlSessionFactoryBean.setMapperLocations(resourceResolver.getResources("mybatis/db2/*.xml"));
        return sqlSessionFactoryBean;
    }
}

配置基于XA协议的事务管理器

@Configuration
public class ConfigXATransaction {
    //创建基于XA协议的事务管理器
    @Bean("xaTransaction")
    public JtaTransactionManager jtaTransactionManager(){
        UserTransaction userTransaction = new UserTransactionImp();
        UserTransactionManager userTransactionManager = new UserTransactionManager();
        return new JtaTransactionManager(userTransaction,userTransactionManager);
    }
}

在service层配置基于XA协议的事务管理器

@Service
public class XAService {

    @Resource
    private XADB1Mapper XADB1Mapper;

    @Resource
    private XADB2Mapper XADB2Mapper;

    // 事务管理器配置
    @Transactional(transactionManager = "xaTransaction")
    public void testXA() {
        XADB1 XADB1 = new XADB1();
        XADB1.setId(2);
        XADB1.setName("xa_db1");
        XADB1Mapper.insert(XADB1);
        // 在此处会抛异常,两条事务都会回滚
        int i = 1/0;
        XADB2 XADB2 = new XADB2();
        XADB2.setId(2);
        XADB2.setName("xa_db2");
        XADB2Mapper.insert(XADB2);
    }
}

源码地址 https://gitee.com/kakalex/xaDemo


版权声明:本文为hitalex2017原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。