栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > 架构设计

数据源动态切换、跨库事物失效问题解决方案

架构设计 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

数据源动态切换、跨库事物失效问题解决方案

数据源动态切换、跨库事物失效问题解决方案
  • 一、问题出现的场景
  • 二、跨库事物失效的原因
  • 三、解决方案
    • 1、自定义跨库事物注解
    • 2、对有标记的请求、保存数据库链接、关闭自动提交
    • 3、对开启了跨库事物方法进行拦截、标记、提交/回滚
  • 四、注意事项
  • 五、压测报告
    • 结论:解决方案性能ok

一、问题出现的场景

系统架构设计、每个企业一个企业库、通过数据源切在平台库、和企业库之间动态切换完成业务操作。

二、跨库事物失效的原因

1、Spring@Transactional不支持跨数据源事物,Spring 事物控制是基于数据库链接进行的,当数据源切换后,数据库链接切换,事物回滚只能回退,当前持有的链接。
2、Spring开启事物后,会将当前数据库及数据库链接资源进行线程绑定,导致数据源切换失效(数据源切换执行后,并未获取到新的数据库链接)。

三、解决方案

基于InheritableThreadLocal + aop 针对添加了跨库事务注解的方法进行拦截、线程标记、覆写mybatis自动提交,通过aop手动提交/回退,实现跨库事务。

1、自定义跨库事物注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MultiTransactional {
}
2、对有标记的请求、保存数据库链接、关闭自动提交


在动态数据源获取数据库链接处特殊处理,如果开启了跨库事物,则返回包装后对connection对象(包装主要为了避免mybatis自动提交和回滚)、并且将对应的数据库链接保存到线程上下文。

3、对开启了跨库事物方法进行拦截、标记、提交/回滚

基于InheritableThreadLocal 对添加了跨库事物注解@MultiTransactional的方法进行拦截
1)在方法执行前:设置multilTransactionalStatus = true;
2)在方法执行异常时:从当前线程上线文获取到所有链接、统一rollback();
3)在方法正常执行结束:从当前线程上线文获取到所有链接、统一commit();

四、注意事项

1、使用InheritableThreadLocal(带继承)能保证线程标记不丢失。
2、需要对执行手动事物的链接对象包装、覆写submit()、rollback()方法、否则mybatis在sql执行后会自动提交,导致事物失败。
3、请求执行结束后(包含正常、异常情况)均要提交/回滚事物、释放资源,避免内存泄漏、链接异常。
4、本文使用了ThreadLoca保存链接,同理也可使用HttpServletRequest对象保存链接资源(会在定时任务等特殊场景下失效),可酌情考虑使用。

五、压测报告

对同一段代码进行三种事务控制: 不添加事务、添加@Transactional、添加@MultiTransactional 进行压测对比。

无事务控制

添加Transactional

添加MultiTransactional
无事务控制
添加Transactional

添加MultiTransactional

无事务控制
添加Transactional

添加MultiTransactional

注:所有异常情况均为 429 Too Many Requests (太多请求)

结论:解决方案性能ok

经过三种事务控制压测结果对比,MultiTransactional注解方式支持跨库事务、没有带来额外的性能压力。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/908400.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号