sharding-jdbc多数据源配置分库分表

Posted 李潇然

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sharding-jdbc多数据源配置分库分表相关的知识,希望对你有一定的参考价值。

由于sharding-jdbc对sql有多种语法限制,如果用同一个数据源,不分表的sql语句也无法规避限制

因此可以使用多数据源方式解决该问题。

1指定mapper注解java接口所在的目录

basePackages = "com.order.mapper.second"

2指定mapper sql语句xml所在的目录

String MAPPER_LOCATION = "classpath:mapper/second/*.xml"

package com.order.config;

import com.order.dao.RangeShardingTableStrategy;
import com.order.dao.ShardingTableStrategy;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.shardingsphere.api.config.sharding.KeyGeneratorConfiguration;
import org.apache.shardingsphere.api.config.sharding.ShardingRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.TableRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.strategy.InlineShardingStrategyConfiguration;
import org.apache.shardingsphere.api.config.sharding.strategy.StandardShardingStrategyConfiguration;
import org.apache.shardingsphere.shardingjdbc.api.ShardingDataSourceFactory;
import org.apache.shardingsphere.spring.boot.util.DataSourceUtil;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

@Configuration
@MapperScan(basePackages = "com.order.mapper.second", sqlSessionFactoryRef = "secondSqlSessionFactory")
public class SecondDataSourceConfig {

    // 精确到目录,以便跟其他数据源隔离
    static final String MAPPER_LOCATION = "classpath:mapper/second/*.xml";
    @Value("${spring.shardingsphere.datasource.order.jdbc-url}")
    private String url;
    @Value("${spring.shardingsphere.datasource.order.username}")
    private String username;
    @Value("${spring.shardingsphere.datasource.order.password}")
    private String password;

    /**
     * 创建sharding-jdbc的DataSource实例
     *
     * @return
     */
    @Bean(name = "secondDataSource")
    @Qualifier("secondDataSource")
    public DataSource shardingDataSource() {
        //return DataSourceBuilder.create().build();
        return getShardingDataSource();
    }

    @Bean(name = "secondSqlSessionFactory")
    public SqlSessionFactory clusterSqlSessionFactory(@Qualifier("secondDataSource") DataSource clusterDataSource)
            throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(clusterDataSource);
        sessionFactory.setMapperLocations(
                new PathMatchingResourcePatternResolver().getResources(SecondDataSourceConfig.MAPPER_LOCATION));
        return sessionFactory.getObject();
    }


    DataSource getShardingDataSource() {
        ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
        shardingRuleConfig.getTableRuleConfigs().add(getOrderTableRuleConfiguration());
        shardingRuleConfig.getBindingTableGroups().add("order_all");
        //shardingRuleConfig.setDefaultDatabaseShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new ShardingTableStrategy()));
        shardingRuleConfig.setDefaultTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new ShardingTableStrategy(),new RangeShardingTableStrategy()));
        try {
            return ShardingDataSourceFactory.createDataSource(createDataSourceMap(), shardingRuleConfig, new Properties());
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static KeyGeneratorConfiguration getKeyGeneratorConfiguration() {
        KeyGeneratorConfiguration result = new KeyGeneratorConfiguration("SNOWFLAKE", "order_id");
        return result;
    }

    TableRuleConfiguration getOrderTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration("order_all", "order.order_all_${0..15}");
        //result.setKeyGeneratorConfig(getKeyGeneratorConfiguration());
        return result;
    }

    @ConfigurationProperties(prefix = "spring.shardingsphere.datasource.order")
    Map<String, DataSource> createDataSourceMap() {
        Map<String, DataSource> result = new HashMap<>();
        // 配置真实数据源
        Map<String, Object> dataSourceProperties = new HashMap<>();
        dataSourceProperties.put("DriverClassName", "com.mysql.jdbc.Driver");
        dataSourceProperties.put("jdbcUrl", url);
        dataSourceProperties.put("username", username);
        dataSourceProperties.put("password", password);
        try {
            DataSource ds = DataSourceUtil.getDataSource("com.zaxxer.hikari.HikariDataSource", dataSourceProperties);
            result.put("order", ds);
        } catch (ReflectiveOperationException e) {
            e.printStackTrace();
        }
        return result;
    }
}

 为了便于查询,需要设置分表策略,范围查询策略

        shardingRuleConfig.setDefaultTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new ShardingTableStrategy(),new RangeShardingTableStrategy()))

这里面2个自定义类如下

ShardingTableStrategy

 

public class ShardingTableStrategy implements PreciseShardingAlgorithm<String> {

    @Override
    public String doSharding(Collection<String> collection, PreciseShardingValue<String> preciseShardingValue) {

        for (String tableName : collection) {
            long divide = Math.abs(preciseShardingValue.getValue().hashCode()) % 16;
            if (tableName.endsWith("" + divide)) {
                return tableName;
            }
        }
        throw new IllegalArgumentException();
    }
}
RangeShardingTableStrategy
public class RangeShardingTableStrategy implements RangeShardingAlgorithm<String> {


    @Override
    public Collection<String> doSharding(Collection<String> collection, RangeShardingValue<String> rangeShardingValue) {
        Collection<String> collect = new ArrayList<>();
        for (int i = 0; i < 16; i++) {
            for (String each : collection) {
                if (each.endsWith(i % collection.size() + "")) {
                    collect.add(each);
                }
            }
        }
        return collect;
    }
}

 

以上是关于sharding-jdbc多数据源配置分库分表的主要内容,如果未能解决你的问题,请参考以下文章

Sharding-JDBC分库分表异常排查

数据库分库分表中间件 Sharding-JDBC 源码分析 —— SQL 路由之分库分表配置

Sharding-JDBC分库分表使用实例

springboot~对应sharding-jdbc实现分库分表

SpringBoot使用sharding-jdbc分库分表

SpringBoot使用Sharding-JDBC分库分表