sharding-jdbc配置类ShardingRuleConfiguration源码分析

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、配置源码到此结束,下篇详细分析使用流程。

参考:策略优化

配置参考:查阅​​​​​​​

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

寅灯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值