Sharding核心配置主要如下(官网):
- 分片规则
分片规则配置的总入口。包含数据源配置、表配置、绑定表配置以及读写分离配置等
-
数据源配置
真实数据源列表
-
表配置
逻辑表名称、数据节点与分表规则的配置
-
数据节点配置
用于配置逻辑表与真实表的映射关系。可分为均匀分布和自定义分布两种形式
-
分片策略配置
对于分片策略存有数据源分片策略和表分片策略两种维度
- 数据源分片策略:
对应于DatabaseShardingStrategy。用于配置数据被分配的目标数据源
- 表分片策略
对应于TableShardingStrategy。用于配置数据被分配的目标表,该目标表存在与该数据的目标数据源内。故表分片策略是依赖与数据源分片策略的结果的
- 数据源分片策略:
- 自增主键生成策略
通过在客户端生成自增主键替换以数据库原生自增主键的方式,做到分布式主键无重复。
1、接下来对各个核心配置进行分析:
package com.nandao.demo.config;
import com.baomidou.mybatisplus.entity.GlobalConfiguration;
import com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean;
import com.google.common.collect.Lists;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.shardingsphere.api.config.masterslave.MasterSlaveRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.ShardingRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.TableRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.strategy.StandardShardingStrategyConfiguration;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.shardingjdbc.api.ShardingDataSourceFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.*;
/**
* @author wanghuainan
* @date 2020/9/8
*/
@Configuration
@MapperScan(basePackages = "com.nandao.demo.dao.sys", sqlSessionTemplateRef = "sysSqlSessionTemplate")
public class SysDataSourceConfig {
/**
* @param dataSource
* @return
* @throws SQLException
*/
@Bean("sysShardingDataSource")
public DataSource getShardingDataSource(@Qualifier("sysDataSource") DataSource dataSource) throws SQLException {
ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
//分片表规则配置
shardingRuleConfig.getTableRuleConfigs().add(new TableRuleConfiguration("car_info", "sysDataSource.car_info${0..9}"));
shardingRuleConfig.getTableRuleConfigs().add(new TableRuleConfiguration("user_info", "sysDataSource.user_info${0..9}"));
//绑定分片表,主要用来路由
shardingRuleConfig.getBindingTableGroups().add("user_info");
shardingRuleConfig.getBindingTableGroups().add("car_info");
//设置默认数据源分片策略;可选
shardingRuleConfig.setDefaultDatabaseShardingStrategyConfig(new StandardShardingStrategyConfiguration("user_id", new PreciseModuloShardingDatabaseAlgorithm()));
//设置默认表分片策略
shardingRuleConfig.setDefaultTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("uid", new PreciseShardingAlgorithm<Long>() {
@Override
public String doSharding(final Collection<String> tableNames, final PreciseShardingValue<Long> shardingValue) {
for (String tableName : tableNames) {
if (tableName.endsWith(shardingValue.getValue() % 10 + "")) {
return tableName;
}
}
throw new UnsupportedOperationException();
}
}));
//也可用此种方案,有时查询效率更高
//shardingRuleConfig.setDefaultTableShardingStrategyConfig(
new MyShardingStrategyConfiguration("gmt_create", SuperTableShardingAlgorithm.class.getName(),
SuperTableShardingRangeAlgorithm.class.getName()));
HashMap<String, DataSource> hashMap = new HashMap<>();
hashMap.put("sysDataSource", dataSource);
Properties properties = new Properties();
properties.setProperty("user.id", "9");
properties.put("sql.show", true);
//主从配置,支持多主多从;可选
shardingRuleConfig.setMasterSlaveRuleConfigs(getMasterSlaveRuleConfigurations());
return ShardingDataSourceFactory.createDataSource(hashMap, shardingRuleConfig, properties);
}
private List<MasterSlaveRuleConfiguration> getMasterSlaveRuleConfigurations() {
MasterSlaveRuleConfiguration masterSlaveRuleConfig1 = new MasterSlaveRuleConfiguration("ds_0", "demo_ds_master_0", Arrays.asList("demo_ds_master_0_slave_0", "demo_ds_master_0_slave_1"));
MasterSlaveRuleConfiguration masterSlaveRuleConfig2 = new MasterSlaveRuleConfiguration("ds_1", "demo_ds_master_1", Arrays.asList("demo_ds_master_1_slave_0", "demo_ds_master_1_slave_1"));
return Lists.newArrayList(masterSlaveRuleConfig1, masterSlaveRuleConfig2);
}
@Bean(name = "sysSqlSessionFactory")
public SqlSessionFactory userSqlSessionFactory(@Qualifier("sysShardingDataSource") DataSource dataSource) throws Exception {
MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
bean.setDataSource(dataSource);
GlobalConfiguration globalConfiguration = new GlobalConfiguration();
globalConfiguration.setDbColumnUnderline(true);
globalConfiguration.setRefresh(true);
bean.setGlobalConfig(globalConfiguration);
bean.setDataSource(dataSource);
bean.setConfigLocation(new ClassPathResource("mybatis.xml"));
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/sys/*.xml"));
return bean.getObject();
}
@Bean(name = "sysTransactionManager")
public PlatformTransactionManager userTransactionManager(@Qualifier("sysShardingDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "sysSqlSessionTemplate")
public SqlSessionTemplate userSqlSessionTemplate(@Qualifier("sysSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
2、ShardingRuleConfiguration 源码分析:
public final class ShardingRuleConfiguration implements RuleConfiguration {
//表规则配置
private Collection<TableRuleConfiguration> tableRuleConfigs = new LinkedList<>();
//绑定表配置
private Collection<String> bindingTableGroups = new LinkedList<>();
//广播表配置
private Collection<String> broadcastTables = new LinkedList<>();
//默认数据源名称
private String defaultDataSourceName;
//默认分库策略
private ShardingStrategyConfiguration defaultDatabaseShardingStrategyConfig;
//默认分片策略
private ShardingStrategyConfiguration defaultTableShardingStrategyConfig;
//默认主键生成工具类
private KeyGeneratorConfiguration defaultKeyGeneratorConfig;
//主从规则配置
private Collection<MasterSlaveRuleConfiguration> masterSlaveRuleConfigs = new LinkedList<>();
//数据脱敏规则配置
private EncryptRuleConfiguration encryptRuleConfig;
}
3、分析ShardingDataSourceFactory#createDataSource中的ShardingRule配置源码:
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class ShardingDataSourceFactory {
/**
* Create sharding data source.
*
* @param dataSourceMap data source map
* @param shardingRuleConfig rule configuration for databases and tables sharding
* @param props properties for data source
* @return sharding data source
* @throws SQLException SQL exception
*/
public static DataSource createDataSource(
final Map<String, DataSource> dataSourceMap, final ShardingRuleConfiguration shardingRuleConfig, final Properties props) throws SQLException {
//创建ShardingDataSource数据源,同时创建sharding rule配置
return new ShardingDataSource(dataSourceMap, new ShardingRule(shardingRuleConfig, dataSourceMap.keySet()), props);
}
}
4、ShardingRule分片规则源码:
public ShardingRule(final ShardingRuleConfiguration shardingRuleConfig, final Collection<String> dataSourceNames) {
Preconditions.checkArgument(null != shardingRuleConfig, "ShardingRuleConfig cannot be null.");
Preconditions.checkArgument(null != dataSourceNames && !dataSourceNames.isEmpty(), "Data sources cannot be empty.");
this.shardingRuleConfig = shardingRuleConfig;
//sharding数据源名称
shardingDataSourceNames = new ShardingDataSourceNames(shardingRuleConfig, dataSourceNames);
//创建表规则集合
tableRules = createTableRules(shardingRuleConfig);
//创建分组绑定表
//1.从tableRules查找
//2.是否广播表,如果是广播表,dataSourceNames.size() == 1 ? dataSourceNames.iterator().next() : shardingRuleConfig.getDefaultDataSourceName();
//3.已上两种情况都不满足,则使用默认数据源创建tableRule
bindingTableRules = createBindingTableRules(shardingRuleConfig.getBindingTableGroups());
//广播表
broadcastTables = shardingRuleConfig.getBroadcastTables();
//默认分库策略
defaultDatabaseShardingStrategy = createDefaultShardingStrategy(shardingRuleConfig.getDefaultDatabaseShardingStrategyConfig());
//默认表分片策略
defaultTableShardingStrategy = createDefaultShardingStrategy(shardingRuleConfig.getDefaultTableShardingStrategyConfig());
//默认主键生成工具类
defaultShardingKeyGenerator = createDefaultKeyGenerator(shardingRuleConfig.getDefaultKeyGeneratorConfig());
//创建主从规则
masterSlaveRules = createMasterSlaveRules(shardingRuleConfig.getMasterSlaveRuleConfigs());
//数据脱敏规则
encryptRule = createEncryptRule(shardingRuleConfig.getEncryptRuleConfig());
}
5、TableRule表规则源码:
public TableRule(final TableRuleConfiguration tableRuleConfig, final ShardingDataSourceNames shardingDataSourceNames, final String defaultGenerateKeyColumn) {
//获取逻辑表
logicTable = tableRuleConfig.getLogicTable().toLowerCase();
//inline表达式解析出真实表,比如:ds_${0..1}.t_order_${[0, 1]}
//解析出来为:
//ds_0.t_order_0
//ds_0.t_order_1
//ds_1.t_order_0
//ds_1.t_order_1
List<String> dataNodes = new InlineExpressionParser(tableRuleConfig.getActualDataNodes()).splitAndEvaluate();
dataNodeIndexMap = new HashMap<>(dataNodes.size(), 1);
//真实表数据节点
//1.如果没有配置真实表,则根据逻辑表、数据源来生成对应真实表数据节点
//2.否则根据inline表达式解析出来的真实表来生成真实数据节点
actualDataNodes = isEmptyDataNodes(dataNodes)
? generateDataNodes(tableRuleConfig.getLogicTable(), shardingDataSourceNames.getDataSourceNames()) : generateDataNodes(dataNodes, shardingDataSourceNames.getDataSourceNames());
//真实表
actualTables = getActualTables();
//数据源->分片策略
databaseShardingStrategy = null == tableRuleConfig.getDatabaseShardingStrategyConfig() ? null : ShardingStrategyFactory.newInstance(tableRuleConfig.getDatabaseShardingStrategyConfig());
//表->分片策略
tableShardingStrategy = null == tableRuleConfig.getTableShardingStrategyConfig() ? null : ShardingStrategyFactory.newInstance(tableRuleConfig.getTableShardingStrategyConfig());
//主键字段
generateKeyColumn = getGenerateKeyColumn(tableRuleConfig.getKeyGeneratorConfig(), defaultGenerateKeyColumn);
//生成主键工具类,比如SNOWFLAKE
shardingKeyGenerator = containsKeyGeneratorConfiguration(tableRuleConfig)
? new ShardingKeyGeneratorServiceLoader().newService(tableRuleConfig.getKeyGeneratorConfig().getType(), tableRuleConfig.getKeyGeneratorConfig().getProperties()) : null;
}
6、配置源码到此结束,下篇详细分析使用流程。
参考:策略优化
配置参考:查阅