Sharding-JDBC 系列
- 第一篇 Sharding-JDBC 源码之启动流程分析(本文)
- 第二篇 Sharding-JDBC 源码之 SQL 解析
- 第三篇 Sharding-JDBC 源码之 SQL 路由
- 第四篇 Sharding-JDBC 源码之 SQL 改写
- 第五篇 Sharding-JDBC 源码之 SQL 执行
- 第六篇 Sharding-JDBC 源码之结果集归并
Sharding-JDBC 是 ShardingSphere 开源的分布式数据库中间件产品之一,提供标准化的数据分片、分布式事务和数据库治理功能,可适用于如Java同构、异构语言、云原生等各种多样化的应用场景。
Sharding-JDBC 在 Java 的 JDBC 层提供额外服务,它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架
目录
接下来,让我们由简入繁,逐渐拉来 Sharding-JDBC 的序幕。
首先基于 SpringBoot2.4 快速搭建一个 Demo,主要 jar 包依赖版本分别是:
- io.shardingsphere.sharding-jdbc-spring-boot-starter:3.0.0.M1
- com.alibaba.druid-spring-boot-starter:1.1.17
- org.mybatis.spring.boot.mybatis-spring-boot-starter:2.1.4
配置 application.properties :
spring.application.name=shardingjdbcdemo
server.port=8080
spring.main.allow-bean-definition-overriding=true
#数据源名称
sharding.jdbc.datasource.names=ds0,ds1
#数据源 ds0 的配置
sharding.jdbc.datasource.ds0.type=com.alibaba.druid.pool.DruidDataSource
sharding.jdbc.datasource.ds0.driver-class-name=com.mysql.cj.jdbc.Driver
sharding.jdbc.datasource.ds0.url=jdbc\:mysql\://localhost\:3306/d_sharding_demo1?useUnicode\=true&characterEncoding\=UTF-8&autoReconnect\=true&failOverReadOnly\=false&allowMultiQueries\=true&serverTimezone=GMT
sharding.jdbc.datasource.ds0.username=root
sharding.jdbc.datasource.ds0.password=123456
sharding.jdbc.datasource.ds0.initialSize=1
sharding.jdbc.datasource.ds0.minIdle=1
sharding.jdbc.datasource.ds0.maxActive=50
#数据源 ds1 的配置
sharding.jdbc.datasource.ds1.type=com.alibaba.druid.pool.DruidDataSource
sharding.jdbc.datasource.ds1.driver-class-name=com.mysql.cj.jdbc.Driver
sharding.jdbc.datasource.ds1.url=jdbc\:mysql\://localhost\:3306/d_sharding_demo2?useUnicode\=true&characterEncoding\=UTF-8&autoReconnect\=true&failOverReadOnly\=false&allowMultiQueries\=true&serverTimezone=GMT
sharding.jdbc.datasource.ds1.username=root
sharding.jdbc.datasource.ds1.password=123456
sharding.jdbc.datasource.ds1.initialSize=1
sharding.jdbc.datasource.ds1.minIdle=1
sharding.jdbc.datasource.ds1.maxActive=50
#控制台展示 sql 语句
sharding.jdbc.config.sharding.props.sql.show=true
#实际节点
sharding.jdbc.config.sharding.tables.t_goods.actual-data-nodes=ds$->{0..1}.t_goods_$->{0..1}
#分表列
sharding.jdbc.config.sharding.tables.t_goods.table-strategy.inline.shardingColumn=goods_id
#分片策略
sharding.jdbc.config.sharding.tables.t_goods.table-strategy.inline.algorithm-expression=t_goods_$->{goods_id % 2}
#分库列
sharding.jdbc.config.sharding.tables.t_goods.databaseStrategy.standard.shardingColumn=type
#分库策略
sharding.jdbc.config.sharding.tables.t_goods.databaseStrategy.standard..preciseAlgorithmClassName=com.example.shardingjdbcdemo.algorithm.MyPreciseShardingAlgorithm
客户端测试程序
@Test
public void query() {
GoodsDTO order = goodsInfoMapper.getByGoodsId(1L,0);
}
源码分析
当执行上面的客户端程序时,Springboot 会去拉取 application.properties
中的配置,下面我们来看下 sharding-jdbc-spring-boot-starter
中的类,
获取 Sharding 配置
@ConfigurationProperties(prefix = "sharding.jdbc.config.sharding")
public class SpringBootShardingRuleConfigurationProperties extends YamlShardingRuleConfiguration {
}
@ConfigurationProperties
注解修饰的类会将配置文件中的属性名称匹配的的值绑定到类的属性字段上。
获取数据源及分库分表策略
@Configuration
@EnableConfigurationProperties({
SpringBootShardingRuleConfigurationProperties.class, SpringBootMasterSlaveRuleConfigurationProperties.class})
public class SpringBootConfiguration implements EnvironmentAware {
@Autowired
private SpringBootShardingRuleConfigurationProperties shardingProperties;
/**
* 1. 实现 EnvironmentAware 接口,获取配置信息
* 2. 根据配置文件信息获取数据源配置
*/
@Override
public void setEnvironment(final Environment environment) {
setDataSourceMap(environment);
}
@SuppressWarnings("unchecked")
private void setDataSourceMap(final Environment environment) {
String prefix = "sharding.jdbc.datasource.";
String dataSources = environment.getProperty(prefix + "names");
// 获取数据源并存入 dataSourceMap 中
for (String each : dataSources.split(",")) {
try {
Map<String, Object> dataSourceProps = PropertyUtil.handle(environment, prefix + each, Map.class);
Preconditions.checkState(!dataSourceProps.isEmpty(), "Wrong datasource properties!");
DataSource dataSource = DataSourceUtil.getDataSource(dataSourceProps.get("type").toString(), dataSourceProps);
dataSourceMap.put(each, dataSource);
} catch (