ShardingSphere 介绍与准备
ShardingSphere 是 Apache 提供的一个分表分库中间件,需要在项目中集成分表功能又或者分库功能可以使用,旧项目使用也无需修改原 SQL,兼容其他 orm 框架;此文章只记录分表功能实现,分库是为了数据库层分流减少数据库的压力,个人建议读写分离使用其他中间件(譬如:MyCat),考虑业务场景,分表是为了解决数据量过大导致查询效率慢的问题,我们可以通过优化分表的规则解决这个问题,另外如果打算在业务层控制读写分离,开发成本会提高并且需要开发人员对业务以及代码编写非常熟悉,能够准确在指定位置切换数据源,操作繁琐,个人不考虑这种方式的读写分离实现方式;当然,本文也会额外介绍多数据源的配置。
依赖
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.1.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.22</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
配置文件参数
spring.datasource.ds0.url=jdbc:mysql://ds0
spring.datasource.ds0.username=***
spring.datasource.ds0.password=***
spring.datasource.ds0.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.ds1.url=jdbc:mysql://ds1 spring.datasource.ds1.username=***
spring.datasource.ds1.password=***
spring.datasource.ds1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.ds2.url=jdbc:mysql://ds2
spring.datasource.ds2.username=*** spring.datasource.ds2.password=***
spring.datasource.ds2.driver-class-name=com.mysql.cj.jdbc.Driver
配置类
/** * 举例配置主数据源,其他次数据源类似,主数据源建议加上 @Primary */
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import org.apache.shardingsphere.transaction.core.TransactionType;
import org.apache.shardingsphere.transaction.core.TransactionTypeHolder;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.sql.SQLException;
@Configuration
@MapperScan(basePackages = "数据库接口层目录", sqlSessionFactoryRef = "mainSqlSessionFactory")
public class OpenDataSourceConfig {
@Autowired
private MybatisPlusInterceptor mybatisPlusInterceptor;
/** * 使用 DruidDataSourceBuilder 创建数据源即可引入对应阿里的数据库连接池 */
@Bean("mainDateSource")
@ConfigurationProperties(prefix = "spring.datasource.ds0")
public DataSource mainDateSource() {
return DruidDataSourceBuilder.create().build();
}
/** * 分表配置 */
@Bean(name = "mainShardingDataSource")
public DataSource mainShardingDataSource(@Qualifier("mainDateSource") DataSource mainDateSource) throws SQLException {
TransactionTypeHolder.set(TransactionType.LOCAL);
// 1、指定需要分表的数据源
Map<String, DataSource> dataSourceMap = new HashMap<>();
dataSourceMap.put("main", mainDateSource);
// 2、分表配置
ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
shardingRuleConfig.getTableRuleConfigs().addAll(CollUtil.newArrayList(pageRecordConfig()));
shardingRuleConfig.setDefaultDataSourceName("main");
return ShardingDataSourceFactory.createDataSource(dataSourceMap, shardingRuleConfig, new Properties());
}
/** * 会话工厂 */
@Bean(name = "mainSqlSessionFactory")
public SqlSessionFactory mainSqlSessionFactory(@Qualifier("mainShardingDataSource") DataSource dataSource) throws Exception {
MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:静态SQL文件的目录"));
MybatisConfiguration configuration = new MybatisConfiguration();
configuration.setJdbcTypeForNull(JdbcType.NULL);
configuration.setMapUnderscoreToCamelCase(true);
configuration.setCacheEnabled(false);
sessionFactory.setConfiguration(configuration);
sessionFactory.setPlugins(mybatisPlusInterceptor);
return sessionFactory.getObject();
}
/** * 事务管理器 */
@Bean(name = "mainTransactionManager")
public DataSourceTransactionManager mainTransactionManager(@Qualifier("mainShardingDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
/** * 分表策略设置 * * @return */
TableRuleConfiguration pageRecordConfig() {
TableRuleConfiguration result = new TableRuleConfiguration("page_record", "main.page_record_${0..15}");
// 配置分表策略,缺省表示使用默认分表策略
result.setTableShardingStrategyConfig(new InlineShardingStrategyConfiguration("id", "page_record_${id % 16}"));
return result;
}
}
注意事项:
- Mysql 使用的版本为 8,因此驱动使用 com.mysql.cj.jdbc.Driver;
- 引入第三方连接池需要指定才会生效,本文中使用阿里连接池,因为数据库地址属性配置名称为 spring.datasource.url,默认连接池的地址属性配置名称为 spring.datasource.jdbc;
- 多数据源情况下需要指定主数据源以及对应的事物管理器。