(springboot系列)springboot+sharding+動態(tài)數(shù)據(jù)源

1. sharding簡介

ShardingSphere是一套開源的分布式數(shù)據(jù)庫中間件解決方案組成的生態(tài)圈,目前已在阿帕奇孵化成功,它由Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar(計(jì)劃中)這3款相互獨(dú)立的產(chǎn)品組成,這里主要介紹shardingjdbc,文檔地址 https://shardingsphere.apache.org/document/current/cn/overview/

2. 使用

1.引入maven包

這里不適用start包,而直接使用原包,這里還需要排除sharding的mysql連接器,使用自己的連接器

<!-- https://mvnrepository.com/artifact/io.shardingsphere/sharding-jdbc-core -->
<dependency>
    <groupId>io.shardingsphere</groupId>
    <artifactId>sharding-jdbc-core</artifactId>
    <version>3.1.0</version>
    <exclusions>
        <exclusion>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </exclusion>
    </exclusions>
</dependency>

2.配置

sharding和動態(tài)數(shù)據(jù)源整合一起,因?yàn)閟harding會全局解析所有sql,在某些情況下mybatis能解析的sql語句sharding是沒辦法解析的,會導(dǎo)致以前的業(yè)務(wù)sql出現(xiàn)問題,所以我們通過動態(tài)數(shù)據(jù)源和注解的形式標(biāo)注哪些sql需要使用sharding的數(shù)據(jù)源,靈活配置

DynamicDataSource

/**
 * 動態(tài)數(shù)據(jù)源
 * Created by tyf on 2019/9/25 0025
 */
public class DynamicDataSource extends AbstractRoutingDataSource {


    //用來保存數(shù)據(jù)源與獲取數(shù)據(jù)源
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

    public DynamicDataSource(DataSource defaultTargetDataSource, Map<String, DataSource> targetDataSources) {
        super.setDefaultTargetDataSource(defaultTargetDataSource);
        super.setTargetDataSources(new HashMap<>(targetDataSources));
        super.afterPropertiesSet();
    }

    public static void setDataSource(String dataSource) {
        contextHolder.set(dataSource);
    }

    public static String getDataSource() {
        return contextHolder.get();
    }

    public static void clearDataSource() {
        contextHolder.remove();
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return getDataSource();
    }
}

ShardingDataSourceAspect 動態(tài)數(shù)據(jù)源aop切面,使用springboot的方式

/**
 * 動態(tài)數(shù)據(jù)源aop切面
 * Created by tyf on 2019/9/25 0025
 */
@Aspect
public class ShardingDataSourceAspect {

    @Around(ExecutionConstant.CONTROLLER + "||" + ExecutionConstant.SERVICE)
    public Object around(ProceedingJoinPoint point) throws Throwable {
        // 獲取方法名
        String methodName = point.getSignature().getName();
        // 反射獲取目標(biāo)類
        Class<?> targetClass = point.getTarget().getClass();
        // 拿到方法對應(yīng)的參數(shù)類型
        Class<?>[] parameterTypes = ((MethodSignature) point.getSignature()).getParameterTypes();
        // 根據(jù)類、方法、參數(shù)類型(重載)獲取到方法的具體信息
        Method method = targetClass.getMethod(methodName, parameterTypes);

        final ShardingDataSource methodAnnotation = AnnotationUtils.findAnnotation(method, ShardingDataSource.class);
        final ShardingDataSource classAnnotation = AnnotationUtils.findAnnotation(targetClass, ShardingDataSource.class);

        //當(dāng)類和方法上都沒注解的時(shí)候,跳過
        if (methodAnnotation == null && classAnnotation == null) {
            return point.proceed();
        }

        DynamicDataSource.setDataSource(DataSourceNames.SHARDING);
        try {
            return point.proceed();
        } finally {
            DynamicDataSource.clearDataSource();
        }
    }

}

ShardingDataSource,注解

/**
 * Created by tyf on 2019/9/25 0025
 */
@Target({ ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ShardingDataSource {
}

DataSourceNames常量

/**
 * Created by tyf on 2019/9/25 0025
 */
public interface DataSourceNames {

    String DEFAULT = "default";
    String SHARDING = "sharding";

}

ShardingConfiguration,sharding配置類,將配置抽象在基礎(chǔ)包中,只有當(dāng)業(yè)務(wù)項(xiàng)目有ShardingRuleConfiguration類之后才會加載sharding配置類

@Configuration
@DependsOn("springTools")
@ConditionalOnBean({ShardingRuleConfiguration.class})
public class ShardingConfiguration {


    /**
     * 代理切面類
     *
     * @return
     */
    @Bean
    public ShardingDataSourceAspect shardingDataSourceAspect() {
        return new ShardingDataSourceAspect();
    }

    /**
     * 多數(shù)據(jù)源,默認(rèn)為springboot數(shù)據(jù)源,使用{@link ShardingDataSource} 標(biāo)記為sharding數(shù)據(jù)源
     *
     * @param dataSourceProperties
     * @param shardingRuleConfiguration
     * @return
     * @throws SQLException
     */
    @Bean
    @Primary
    public DynamicDataSource dataSource(DataSourceProperties dataSourceProperties, ShardingRuleConfiguration shardingRuleConfiguration) throws SQLException {
        //初始化springboot數(shù)據(jù)源
        final DataSource dataSource = dataSourceProperties.initializeDataSourceBuilder().build();

        //設(shè)置動態(tài)數(shù)據(jù)源
        Map<String, DataSource> targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceNames.DEFAULT, dataSource);
        targetDataSources.put(DataSourceNames.SHARDING, getShardingDataSource(dataSource, shardingRuleConfiguration));
        return new DynamicDataSource(dataSource, targetDataSources);
    }


    private DataSource getShardingDataSource(DataSource dataSource, ShardingRuleConfiguration shardingRuleConfiguration) throws SQLException {
        final Properties properties = new Properties();

        // 獲取數(shù)據(jù)源對象
        final DataSource shardingDatasource = ShardingDataSourceFactory.createDataSource(ImmutableMap.of("ds0", dataSource),
                shardingRuleConfiguration, new ConcurrentHashMap(), properties);
        return shardingDatasource;
    }

}

在業(yè)務(wù)項(xiàng)目中,你只需要配置ShardingRuleConfiguration即可開箱使用sharding了,例如

    /**
     * sharding分片規(guī)則
     *
     * @return
     */
    @Bean
    @Primary
    public ShardingRuleConfiguration shardingRuleConfiguration() {
        final ShardingRuleConfiguration shardingRuleConfiguration = new ShardingRuleConfiguration();
        TableRuleConfiguration sappPaperRankingTableRuleConfig = new TableRuleConfiguration();
        sappPaperRankingTableRuleConfig.setLogicTable("sapp_paper_ranking");

        //選需要分片的對應(yīng)的庫和表
        sappPaperRankingTableRuleConfig.setActualDataNodes("ds0.sapp_paper_ranking_0${1..9},ds0.sapp_paper_ranking_${10..31}");
        // 配置分庫 + 分表策略
        sappPaperRankingTableRuleConfig.setDatabaseShardingStrategyConfig(new NoneShardingStrategyConfiguration());
        sappPaperRankingTableRuleConfig.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration(
                "create_date", new SappPaperRankingPreciseShardingAlgorithm()));
        // 配置分片規(guī)則
        shardingRuleConfiguration.getTableRuleConfigs().add(sappPaperRankingTableRuleConfig);
        return shardingRuleConfiguration;
    }
    
    
    /**
     * 精確分片算法,=與IN進(jìn)行分片
     */
    public class SappPaperRankingPreciseShardingAlgorithm implements PreciseShardingAlgorithm<Integer> {
        @Override
        public String doSharding(Collection<String> tableNames/*表名*/, PreciseShardingValue<Integer> shardingValue /*分片鍵*/) {
    
            final Integer uid = shardingValue.getValue();
            
            /*省略*/
            
            throw new UnsupportedOperationException();
        }
    }

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容