在一些复杂的应用开发中,一个应用可能会涉及到连接多个数据源,所谓多数据源这里就定义为至少连接两个及以上的数据库了。
下面列举两种常用的场景:
一种是读写分离的数据源,例如一个读库和一个写库,读库负责各种查询操作,写库负责各种添加、修改、删除。
另一种是多个数据源之间并没有特别明显的操作,只是程序在一个流程中可能需要同时从A数据源和B数据源中取数据或者同时往两个数据库插入数据等操作。
对于这种多数据的应用中,数据源就是一种典型的分布式场景,因此系统在多个数据源间的数据操作必须做好事务控制。在springboot的官网中发现其支持的分布式事务有三种Atomikos 、Bitronix、Narayana。本文涉及内容中使用的分布式事务控制是Atomikos,感兴趣的可以查看https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-jta.html。
当然分布式事务的作用并不仅仅应用于多数据源。例如:在做数据插入的时候往一个kafka消息队列写消息,如果信息很重要同样需要保证分布式数据的一致性。
一、了解多数据源配置中的那些坑
其实目前网上已经有许多的关于SpringBoot+Mybatis+druid+Atomikos技术栈的文章,在这里也很感谢那些乐于分享的同行们。本文中涉及的许多的问题也是吸纳了许多中外文相关技术博客文档的优点,算是站在巨人的肩膀做一次总结吧。抛开废话,下面列举一些几点多数据源带来的坑吧。
- 配置麻烦,尤其是对于许多开发的新手,看了许多网上的文章,也许还配置不对,还有面对一堆的文章,可能还无法鉴别那些文章的方法是比较可行的。
- 配置了多数据源后发现加入事务后并不能完成数据源的切换。
- 配置多数据源时发现增加了许多的配置工作量。
- springboot环境下mybatis应用打成jar包后无法扫描别名。
二、如何配置一个springboot多数据源项目
本文使用的技术栈是:SpringBoot+Mybatis+druid+Atomikos,因此使用其他技术栈的可以参考他人博客或者是根据本文内容改造。
重要的技术框架依赖:
<!-- ali druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.6</version>
</dependency>
<!-- mybatis spring -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
<!--atomikos transaction management-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>
注意:对于使用mysql jdbc 6.0的同鞋必须更新druid到最新的1.1.6,否则druid无法支持分布式事务。感兴趣的可查看官方的release说明。
- 编写AbstractDataSourceConfig抽象数据源配置
/**
* 针对springboot的数据源配置
*
* @author yu on 2017/12/28.
*/
public abstract class AbstractDataSourceConfig {
protected DataSource getDataSource(Environment env,String prefix,String dataSourceName){