背景

框架之前完成了多数据源的动态切换及事务的处理,想更近一步提供一个简单的跨库事务处理功能,经过网上的搜索调研,大致有XA事务/SEGA事务/TCC事务等方案,因为业务主要涉及政府及企业且并发量不大,所以采用XA事务,虽然性能有所损失,但是可以保证数据的强一致性

方案设计

针对注册的数据源拷贝一份用于XA事务,使得本地事务和XA全局事务相互独立可选择的使用

Maven配置

引入atomikos第三方组件

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jta-atomikos</artifactId></dependency>

注册XA数据源

使用Druid连接池,需要使用DruidXADataSource数据源对象,再使用AtomikosDataSourceBean进行包装

注册数据源时针对同一个连接注册两份,一份正常数据源,一份用于XA事务的数据源,数据源标识区分并关联

因为spring默认注册了XA事务管理器后,所有事务操作不再走本地事务,我们通过切换不同的数据源决定走本地事务还是XA事务

 //主数据源xa模式@Bean@Qualifier("masterXADataSource")public DataSource masterXADataSource() {DruidXADataSource datasource = new DruidXADataSource();if(driverClassName.equals("com.mysql.cj.jdbc.Driver")){if(!dbUrl.contains("useOldAliasMetadataBehavior")){dbUrl += "&useOldAliasMetadataBehavior=true";}if(!dbUrl.contains("useAffectedRows")){dbUrl += "&useAffectedRows=true";}}datasource.setUrl(this.dbUrl);datasource.setUsername(username);datasource.setPassword(password);datasource.setDriverClassName(driverClassName);//configurationdatasource.setInitialSize(1);datasource.setMinIdle(3);datasource.setMaxActive(20);datasource.setMaxWait(60000);datasource.setTimeBetweenEvictionRunsMillis(60000);datasource.setMinEvictableIdleTimeMillis(60000);datasource.setValidationQuery("select 'x'");datasource.setTestWhileIdle(true);datasource.setTestOnBorrow(false);datasource.setTestOnReturn(false);datasource.setPoolPreparedStatements(true);datasource.setMaxPoolPreparedStatementPerConnectionSize(20);datasource.setLogAbandoned(false); //移除泄露连接发生是是否记录日志try {datasource.setFilters("stat,slf4j");} catch (SQLException e) {logger.error("druid configuration initialization filter", e);}datasource.setConnectionProperties("druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000");//connectionProperties);AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();atomikosDataSourceBean.setXaDataSourceClassName("com.alibaba.druid.pool.xa.DruidXADataSource");atomikosDataSourceBean.setUniqueResourceName("master-xa");atomikosDataSourceBean.setXaDataSource(datasource);atomikosDataSourceBean.setPoolSize(5);atomikosDataSourceBean.setMaxPoolSize(20);atomikosDataSourceBean.setTestQuery("select 1");return atomikosDataSourceBean;}

注册XA事务管理器

使用spring内置的JtaTransactionManager事务管理器对象,设置AllowCustomIsolationLevels为true,否则指定自定义事务隔离级别会报错

    //xa模式全局事务管理器@Bean(name = "jtaTransactionManager")public PlatformTransactionManager transactionManager() throws Throwable {UserTransactionManager userTransactionManager = new UserTransactionManager();UserTransaction userTransaction = new UserTransactionImp();JtaTransactionManager jtaTransactionManager =  new JtaTransactionManager(userTransaction, userTransactionManager);jtaTransactionManager.setAllowCustomIsolationLevels(true);return jtaTransactionManager;}

定义XA事务切面

自定义注解@GlobalTransactional并定义对应切面,使用指定注解时在ThreadLocal变量值进行标识,组合

@Transactional注解指定XA事务管理器,在切换数据原时判断当前是否在XA事物中,从而切换不同的数据源

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Transactional(rollbackFor = Exception.class,isolation = Isolation.READ_UNCOMMITTED,transactionManager = "jtaTransactionManager")
public @interface GlobalTransactional {}
@Aspect
@Component
@Order(value = 99)
public class GlobalTransitionAspect {private static Logger logger = LoggerFactory.getLogger(GlobalTransitionAspect.class);@Autowiredprivate DynamicDataSource dynamicDataSource;/*** 切面点 指定注解*/@Pointcut("@annotation(com.code2roc.fastkernel.datasource.GlobalTransactional) " +"|| @within(com.code2roc.fastkernel.datasource.GlobalTransactional)")public void dataSourcePointCut() {}/*** 拦截方法指定为 dataSourcePointCut*/@Around("dataSourcePointCut()")public Object around(ProceedingJoinPoint point) throws Throwable {MethodSignature signature = (MethodSignature) point.getSignature();Method method = signature.getMethod();GlobalTransactional methodAnnotation = method.getAnnotation(GlobalTransactional.class);if (methodAnnotation != null) {DataSourceContextHolder.tagGlobal();logger.info("标记全局事务");}try {return point.proceed();} finally {logger.info("清除全局事务");DataSourceContextHolder.clearGlobal();}}
}
public class DataSourceContextHolder {private static Logger log = LoggerFactory.getLogger(DataSourceContextHolder.class);// 对当前线程的操作-线程安全的private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();private static final ThreadLocal<String> contextGlobalHolder = new ThreadLocal<String>();// 调用此方法,切换数据源public static void setDataSource(String dataSource) {contextHolder.set(dataSource);log.debug("已切换到数据源:{}", dataSource);}// 获取数据源public static String getDataSource() {String value = contextHolder.get();if (StringUtil.isEmpty(value)) {value = "master";}if (!StringUtil.isEmpty(getGlobal())) {value = value + "-xa";}return value;}// 删除数据源public static void clearDataSource() {contextHolder.remove();log.debug("已切换到主数据源");}//====================全局事务标记================public static void tagGlobal() {contextGlobalHolder.set("1");}public static String getGlobal() {String value = contextGlobalHolder.get();return value;}public static void clearGlobal() {contextGlobalHolder.remove();}//===================================================
}

配置XA事务日志

通过在resource文件夹下创建transactions.properties文件可以指定XA事务日志的存储路径

com.atomikos.icatch.log_base_dir= tempfiles/transition/

SpringBoot整合atomikos实现跨库事务相关推荐

  1. Spring+Hibernate+Atomikos集成构建JTA的分布式事务--解决多数据源跨库事务

    一.概念 分布式事务 分布式事务是指事务的参与者.支持事务的服务器.资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上.简言之,同时操作多个数据库保持事务的统一,达到跨库事务的效果. JT ...

  2. 事务 跨库事务 分布式事务及解决方案

    什么是事务? 本地事务 事务传播行为: 事务的四大特性 ACID 并发事务产生的问题可以分为4类 事务的隔离级别 什么是分布式事务 分布式涉及到的原理: CAP原理: BASE理论 柔性事务和刚性事务 ...

  3. springboot整合atomikos实践—单体项目多数据源整合

    springboot整合atomikos-单体项目多数据源整合 最近管理后台增加了其他数据库的一些操作,如果只是简单的切换数据源的话使用动态数据源就可以实现,但动态数据源切换容易,加上事务处理就非常麻 ...

  4. 两个不同的数据库如何跨库事务

    首先我们要明白同一实例,简单来说就是一个ip,如果两个数据库位于同一个ip,就是同一实例.其实实例并不相当于ip, 他其实相当于服务,也就是serve. 这样的两个或多个就可以跨库事务,比如 begi ...

  5. SpringBoot整合Mybatis,并实现事务控制

    SpringBoot整合Mybatis,并实现事务控制 1. 在pom文件里添加相关maven文件 <parent><groupId>org.springframework.b ...

  6. ssm 跨库查询_SSM使用AbstractRoutingDataSource后究竟如何解决跨库事务

    Setting: 绑定三个数据源(XA规范),将三个实例绑定到AbStractoutingDataSource的实例MultiDataSource(自定义的)对象中,mybatis  SqlSessi ...

  7. Best Efforts 1PC 跨库事务

    Best Efforts 1PC 跨库事务 一.背景介绍 分布式事务主要解决两种事务问题,一个是跨库事务,另一个是跨服务事务:跨库是指在一个事务里面包含多个数据源的数据库操作.跨服务是一个事务中包行多 ...

  8. GTS全局事务测试-单DRDS跨库事务

    全局事务服务GTS是一款高性能.高可靠.接入简单的分布式事务中间件,用于解决分布式环境下的数据一致性问题.DRDS特定SQL使用方式; 不同数据库全局事务一致性测试是使用注解的方式. 1.  单DRD ...

  9. 披荆斩棘之springboot整合atomikos

    披荆斩棘之springboot整合atomikos 1.导入jar包 <dependency><groupId>org.springframework.boot</gro ...

最新文章

  1. 腾讯AI开源框架Angel 3.0重磅发布:超50万行代码,支持3种算法,打造全栈机器学习平台...
  2. centos 编译安装mysql
  3. Windows下lex 与 yacc的使用
  4. tomcat启动报错:Bean name 'XXX' is already used in this beans element
  5. Anaconda配置多spyder多python环境
  6. seo图片的alt属性介绍及写法?
  7. 20201008:力扣209周周赛题解(下)
  8. java 上调下移_java – 在调整框架大小时,JLabel的位置会更...
  9. mysql最长字段_在mysql中使用GROUP BY时,如何选择最长的文本字段?
  10. bootstrap-validation 对表单进行比较全的验证
  11. 2022年 javaJDK下载安装步骤及环境变量配置【超详细】
  12. Python3 百度图片 美女 下载 爬虫 多线程
  13. m3u8播放器 android,在android中播放m3u8视频
  14. Vmware中win7联网
  15. word表格分开快捷键_Word使用技巧(表格技巧、快捷键)
  16. ue4 本地化要点详解
  17. ERP系统和CRM系统
  18. html分享到微博,h5页面分享到微信、朋友圈、新浪微博、QQ空间、QQ好友组件
  19. [html5游戏开发]数独游戏-完整算法-开源讲座
  20. 计算机应用程序没声音,电脑突然没声音,多半是这三个原因导致的-维修经验...

热门文章

  1. dns使用tcp/53端口
  2. Linux权限drwxrwxrwx相关详细说明
  3. 【计算机网络安全毕设之基于tornado+CNN的网络入侵检测可视化管理系统-哔哩哔哩】 https://b23.tv/bVI0Big
  4. 5.vue知识点vue router
  5. strncmp()详解
  6. MATLAB 散点数据拟合曲线
  7. 中运量71路线路图_试乘中运量71路后的一些感想
  8. 使用ssh tunnel + sock5 穿越防火墙
  9. java php对话段子,聊天经典套路句子 搞笑对话段子让你常笑一个假期
  10. Linux 查询指定时间段的日志