SpringBoot+Durid+dynamic-datasource实现多数据源分布式事务

news2024/11/15 15:29:16

SpringBoot+Durid+dynamic实现多数据源分布式事务

在这里插入图片描述

引言:

在现代的应用程序中,使用多个数据源来处理不同的业务需求已成为常态。然而,处理多数据源之间的分布式事务是一个复杂的问题。本文将介绍如何使用Spring Boot、Druid和dynamic-datasource-spring-boot-starter来实现多数据源的分布式事务。

背景

在传统的单数据源应用中,事务管理相对简单。但当引入多个数据源时,事务管理变得更加复杂。为了解决这个问题,我们将使用Spring Boot作为应用程序的基础框架,Druid作为数据源连接池,并结合dynamic-datasource-spring-boot-starter来实现动态数据源切换和分布式事务管理。

集成Druid数据源连接池和dynamic动态数据源切换和分布式事务管理

Druid是一款高性能的数据库连接池,具有强大的监控和统计功能。在Spring Boot项目中集成Druid非常简单,只需添加相关依赖并进行配置即可。可以通过以下步骤来完成集成:

  1. 在pom.xml文件中添加依赖。
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.16</version>
</dependency>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>3.5.2</version>
</dependency>
  1. 在application.properties或application.yml文件中配置Druid和dynamic的相关参数。
spring:
  datasource:
    dynamic:
      # druid连接池设置
      druid:
        # 配置初始化线程数
        initialSize: 5
        # 最小线程数
        minIdle: 5
        # CPU核数+1,也可以大些但不要超过20,数据库加锁时连接过多性能下降
        maxActive: 11
        # 最大等待时间,内网:800,外网:1200(三次握手1s)
        maxWait: 60000
        # 连接可空闲存活时间(ms)
        timeBetweenEvictionRunsMillis: 60000
        # 连接保持空闲而不被驱逐的最长存活时间(ms)
        minEvictableIdleTimeMillis: 300000
        # 用来检测连接是否有效的sql,如果validationQuery为空,那么testOnBorrow、testOnReturn、testWhileIdle这三个参数都不会起作用
        validationQuery: SELECT 1
        # 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效;
        testWhileIdle: true
        # 建议配置为false,申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
        testOnBorrow: false
        # 建议配置为false,归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能;
        testOnReturn: false
        # PSCache对支持游标的数据库性能提升巨大
        poolPreparedStatements: true
        # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
        filters: stat
        # 保持minIdle数量的长连接
        keepAlive: true
        # 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。
        # 在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100。缺省值为-1
        maxPoolPreparedStatementPerConnectionSize: 20
        # 是否合并多个DruidDataSource的监控数据
        useGlobalDataSourceStat: true
        # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
        connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
      primary: huawei
      datasource:
        # 主库数据源
        master:
          driverClassName: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://10.211.55.6:13306/ddz?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true
          username: root
          password: root
        # 从库数据源
        slave:
          driverClassName: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://10.211.55.5:13306/ddz?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true
          username: root
          password: root
# MyBatis Plus配置
mybatis-plus:
  # 搜索指定包别名
  typeAliasesPackage: com.ddz.**.domain
  # 配置mapper的扫描,找到所有的mapper.xml映射文件
  mapperLocations: classpath*:mapper/**/*Mapper.xml
  configuration:
    # 使全局的映射器启用或禁用缓存
    cache-enabled: true
    # 允许JDBC 支持自动生成主键
    use-generated-keys: true
    # 配置默认的执行器.SIMPLE就是普通执行器;REUSE执行器会重用预处理语句(prepared statements);BATCH执行器将重用语句并执行批量更新
    default-executor-type: simple
    # 指定 MyBatis 所用日志的具体实现
    log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
    # 使用驼峰命名法转换字段
    map-underscore-to-camel-case: true
  1. 创建两个Mapper类和实体类
@DS("master")
public interface UserMapper extends BaseMapper<User> {
    /**
     * 新增数据
     *
     * @param user 实例对象
     * @return 影响行数
     */
    int insertSql(User user);

}

@DS("slave")
public interface ScoreMapper extends BaseMapper<Score> {
    /**
     * 新增数据
     *
     * @param score 实例对象
     * @return 影响行数
     */
    int insertSql(Score score);
}

@Data
public class User {

    private Integer id;

    private String name;

    private Integer balance;

    private String remark;

    public User(String name, Integer balance) {
        this.name = name;
        this.balance = balance;
    }
}

@Data
public class Score {
    private Integer id;

    private Integer count;

    public Score(Integer count) {
        this.count = count;
    }
}
  1. 编写Controller测试
    给方法加上@DSTransactional注解实现事务管理
@RestController
@RequestMapping("user")
public class UserController {

    @Resource
    private UserMapper userMapper;

    @Resource
    private ScoreMapper scoreMapper;

    @GetMapping("/get")
    @DSTransactional
    public void get() {
    	// 随机触发异常检查两个数据源的一致性
        int i = random.nextInt(10);
        userMapper.insertSql(new User("ddz", i));
        scoreMapper.insertSql(new Score(i*10));
        Random random = new Random();
        if (i % 2 == 0) {
            i = 1 / 0;
        }
    }
}
  1. 需要durid监控页面的添加配置类
@Configuration
public class DruidConfig {
    /**
     * 配置Druid 监控启动页面
     *
     * @return servletRegistrationBean
     */
    @Bean
    @ConditionalOnMissingBean
    public ServletRegistrationBean<Servlet> druidStartViewServlet() {
        ServletRegistrationBean<Servlet> servletRegistrationBean = new ServletRegistrationBean<Servlet>(new StatViewServlet(), "/druid/*");
        // 白名单
        servletRegistrationBean.addInitParameter("allow", "127.0.0.1");
        // 黑名单
//        servletRegistrationBean.addInitParameter("deny", "");
        // 登录查看信息的账密,用于登录Druid监控后台
        servletRegistrationBean.addInitParameter("loginUsername", "ddz");
        servletRegistrationBean.addInitParameter("loginPassword", "ddz2023");
        // 是否能够重置数据
        servletRegistrationBean.addInitParameter("resetEnable", "true");
        return servletRegistrationBean;
    }
 
    /**
     * Druid监控过滤器配置规则
     * ConditionalOnMissingBean 防止注册相同的bean
     *
     * @return filterFilterRegistrationBean
     */
    @Bean
    @ConditionalOnMissingBean
    public FilterRegistrationBean<Filter> filterRegistrationBean() {
        FilterRegistrationBean<Filter> filterFilterRegistrationBean = new FilterRegistrationBean<>();
        filterFilterRegistrationBean.setFilter(new WebStatFilter());
        // 添加过滤规则
        filterFilterRegistrationBean.addUrlPatterns("/*");
        // 添加不需要忽略的格式信息
        filterFilterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
        return filterFilterRegistrationBean;
    }
}
  1. 添加好配置类后重启项目在页面输入http://127.0.0.1:8080/druid/login.html访问
    在这里插入图片描述

分布式事务的注意事项

在使用多数据源进行分布式事务时,需要注意以下几点:

  • 数据源配置和事务管理的正确性,包括数据源的连接信息、事务的传播行为等。
  • 事务的超时和回滚策略,确保事务在适当的时间内完成或回滚。
  • 对于不同数据源之间的数据一致性要求高的场景,可以使用分布式事务管理器(如Atomikos、Bitronix等)来实现XA事务。
  • 针对不同的数据库类型,可能需要配置特定的事务管理器和驱动程序。

总结

本文介绍了如何使用Spring Boot、Druid和dynamic-datasource-spring-boot-starter来实现多数据源的分布式事务。通过合理配置数据源连接池、动态数据源和事务管理,我们可以有效地处理多数据源下的事务一致性问题。在实际应用中,根据具体场景和需求,可以选择适合的分布式事务管理方案。

参考资料:

dynamic-datasource-spring-boot-starter文档:https://www.kancloud.cn/tracy5546/dynamic-datasource/2264611
Spring事务管理文档:https://docs.spring.io/spring-framework/docs/current/reference/html/data-access.html#transaction
Druid官方文档:https://github.com/alibaba/druid

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/655963.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java娱乐新闻系统Myeclipse开发mysql数据库web结构jsp编程计算机网页项目wap

一、源码特点 java 娱乐新闻系统是一套完善的java web wap信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0&…

python---------bs4爬取数据的一种神器

作者前言 欢迎小可爱们前来借鉴我的gtieehttps://gitee.com/qin-laoda 目录 Beautiful Soup的简介 解析⼯具对⽐ BeautifulSoup的基本使⽤ 解析器 搜索⽂档树 CSS常⽤选择器介绍 select和css选择器提取元素 _______________________________________________ 前面我已经…

MongoDB快速实战与基本原理-01

一、MongoDB介绍 1、什么是MongoDB MongoDB是 一个文档数据库&#xff08;以 JSON 为数据模型&#xff09; &#xff0c;由C语言编写&#xff0c;旨在 为 WEB应用提供可扩展的高性能数据存储解决方案。 文档来自于“ JSON Document”&#xff0c;并非我们一般理解的 PDF&am…

Nik Color Efex 滤镜详解(2/5)

交叉冲印 Cross Processing 提供多种选项来处理 C41 - E6&#xff08;用幻灯片显影液处理彩色底片&#xff09;和 E6 - C41&#xff08;用彩色底片显影液处理幻灯片&#xff09;。 方法 Method 选择预设。 强度 Strength 控制滤镜效果程度。 黑暗对比度 Dark Contrasts 使用新…

这本书解开了我心中多年的疑惑,也推荐给你

我对地理一直比较感兴趣&#xff0c;中学时知识掌握的比较扎实&#xff0c;分得清洋流走向、季风信风、世界渔场等等&#xff0c;长期闲置不用已经遗忘的差不多。当时看地理真的是地理&#xff0c;现在看地理&#xff0c;不单单只是地理&#xff0c;还有政治、军事、经济、文化…

港科夜闻|香港科大工学院陈浩教授获选2023年亚洲青年科学家

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、香港科大工学院陈浩教授获选2023年亚洲青年科学家。亚洲青年科学家基金项目于2022年推出&#xff0c;是一项私人资助的研究奖学金计划&#xff0c;旨在鼓励和支持亚洲区内的青年科学家进行推动变革的创新研究&#xff0c…

springCloudAlibaba组件-Nacos-服务注册与心跳机制(二)

文章目录 nacos服务注册流程图专业术语服务注册执行流程 nacos服务注册流程图 专业术语 1.服务注册&#xff1a;为了将所有的微服务都方便管理&#xff0c;需要将自身的信息&#xff08;ip地址、端口号、服务名称&#xff09;以http请求方式调用nacos注册中心接口都放到nacos服…

有趣的数学 求和符号Σ (sigma)简述

一、简单相加 符号∑&#xff08;sigma&#xff09;通常用于表示多个项的总和。这个符号通常伴随着一个索引&#xff0c;该索引变化以包含总和中必须考虑的所有术语。 例如&#xff0c;݊第一个整数的和可以用以下方式表示&#xff1a; 或者&#xff0c;这两种表示意思都是一样…

【JS】中 ?.、??、??= 的用法和含义

今天分享几个处理空值简单的方法&#xff0c;避免使用三目运算、与或、if else时增加冗余的代&#xff0c;希望对大家有帮助。 可选链(?.) let a; let b a.?age; 含义&#xff1a; 可选链&#xff0c;只有当a存在,同时 a 具有 age 属性的时候,才会把值赋给b,否则就会将 u…

【FPGA入门】第二篇、ISE软件的使用

目录 第一部分、新建工程 第二部分、添加顶层文件 第三部分、添加管脚约束文件 第四部分、生成bit文件 第五部分、连接开发板&#xff0c;下载bit文件 第六部分、总结 第一部分、新建工程 第一步、如果提前建立了工程文件夹&#xff0c;那么这里就需要去掉生成子文件夹的…

字符串--const类型限定符、字符处理函数(修改首字母的大小写)、数值字符串向数值得转换

目录 一、const类型限定符 二、字符处理函数 三、数值字符串向函数值转换 一、const类型限定符 通过采用指针或数组作函数参数&#xff0c;可使调用者获得修改后的数据&#xff0c;但有时我们只希望将数据传到被调函数的内部&#xff0c;而并不希望它们在函数内被修改&…

Spring6 JdbcTemplate和事务

文章目录 1、JdbcTemplate1.1、简介1.2、准备工作1.3、实现CURD①装配 JdbcTemplate②测试增删改功能③查询数据返回对象④查询数据返回list集合⑤查询返回单个的值 2、声明式事务概念2.1、事务基本概念①什么是事务②事务的特性 2.2、编程式事务2.3、声明式事务 3、基于注解的…

AI无处不在,科技改变生活:开放原子全球开源峰会参会感悟

目录 前言 英特尔的开源之路 拥抱人工智能 AIGC的浪潮之巅 全链路AI解决方案 极致性能优化 结束语 前言 2023年开放原子全球开源峰会 目前中国源代码贡献量已达到世界第二&#xff0c;开源软件开发者数量也已突破800万&#xff0c;居全球第二。在众多开发者的关注下&…

2.部署Keystone服务

在OpenStack的框架体系中Keystone的作用类似于一个服务总线&#xff0c;为OpenStack提供身份管理服务&#xff0c;包括用户认证&#xff0c;服务认证和口令认证&#xff0c;其他服务通过Keystone来注册服务的Endpoint&#xff08;端点&#xff09;&#xff0c;针对服务的任何调…

50 最佳实践-安全最佳实践-Libvirt鉴权

文章目录 50 最佳实践-安全最佳实践-Libvirt鉴权50.1 简介50.2 开启libvirt鉴权50.3 管理SASL 50 最佳实践-安全最佳实践-Libvirt鉴权 50.1 简介 用户使用libvirt远程调用功能时&#xff0c;如果不进行任何鉴权校验&#xff0c;所有连接到主机所在网络的第三方程序都可以通过…

一道北大强基题背后的故事(四)——数学之美,美在哪里?

早点关注我&#xff0c;精彩不错过&#xff01; 在前面文章中&#xff0c;我们重点聊了[((1 sqrt(5)) / 2) ^ 12]这道题可能的弯路&#xff0c;出题思路和这道题设计巧妙的结论&#xff0c;相关内容请戳&#xff1a; 一道北大强基题背后的故事&#xff08;三&#xff09;——什…

MTK 平台相机bringup流程

和你一起终身学习&#xff0c;这里是程序员Android 经典好文推荐&#xff0c;通过阅读本文&#xff0c;您将收获以下知识点: 一、Camera 框架介绍二、Camera Bringup 需要配置的文件三、复盘总结 一、Camera 框架介绍 Camera 的框架分为 Kernel 部分和 hal 部分&#xff0c;其中…

需求分析引言:架构漫谈(一)

本文主要对架构的概念做一些介绍&#xff0c;并引申出需求分析的重要性。 后续准备做一个系列&#xff0c;定期介绍我工作以来的一些需求实现的案例。 注&#xff1a;因为架构的内容比较庞大&#xff0c;里面的每个点&#xff0c;都可以扩展成一系列的文章&#xff0c; 因此&am…

基于Java精品酒销售管理系统设计实现(源码+lw+部署文档+讲解等)

博主介绍&#xff1a; ✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精…

PoseiSwap 即将在 6 月 18 日开启 IDO,白名单申请者超 14000 人

根据PoseiSwap官方公告&#xff0c;PoseiSwap正式确定了将在6月18日0&#xff1a;00&#xff08;UTC&#xff09;正式在Bounce上开启IDO活动&#xff0c;目前本次活动的白名单申请用户已经突破了14000人。除了Bounce外&#xff0c;PoseiSwap将陆续在BitForex&#xff08;6月23日…