美文网首页
(springboot系列)springboot+shardin

(springboot系列)springboot+shardin

作者: 兔兔二号 | 来源:发表于2019-10-12 15:33 被阅读0次

    1. sharding简介

    ShardingSphere是一套开源的分布式数据库中间件解决方案组成的生态圈,目前已在阿帕奇孵化成功,它由Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar(计划中)这3款相互独立的产品组成,这里主要介绍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和动态数据源整合一起,因为sharding会全局解析所有sql,在某些情况下mybatis能解析的sql语句sharding是没办法解析的,会导致以前的业务sql出现问题,所以我们通过动态数据源和注解的形式标注哪些sql需要使用sharding的数据源,灵活配置

    DynamicDataSource

    /**
     * 动态数据源
     * Created by tyf on 2019/9/25 0025
     */
    public class DynamicDataSource extends AbstractRoutingDataSource {
    
    
        //用来保存数据源与获取数据源
        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 动态数据源aop切面,使用springboot的方式

    /**
     * 动态数据源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();
            // 反射获取目标类
            Class<?> targetClass = point.getTarget().getClass();
            // 拿到方法对应的参数类型
            Class<?>[] parameterTypes = ((MethodSignature) point.getSignature()).getParameterTypes();
            // 根据类、方法、参数类型(重载)获取到方法的具体信息
            Method method = targetClass.getMethod(methodName, parameterTypes);
    
            final ShardingDataSource methodAnnotation = AnnotationUtils.findAnnotation(method, ShardingDataSource.class);
            final ShardingDataSource classAnnotation = AnnotationUtils.findAnnotation(targetClass, ShardingDataSource.class);
    
            //当类和方法上都没注解的时候,跳过
            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配置类,将配置抽象在基础包中,只有当业务项目有ShardingRuleConfiguration类之后才会加载sharding配置类

    @Configuration
    @DependsOn("springTools")
    @ConditionalOnBean({ShardingRuleConfiguration.class})
    public class ShardingConfiguration {
    
    
        /**
         * 代理切面类
         *
         * @return
         */
        @Bean
        public ShardingDataSourceAspect shardingDataSourceAspect() {
            return new ShardingDataSourceAspect();
        }
    
        /**
         * 多数据源,默认为springboot数据源,使用{@link ShardingDataSource} 标记为sharding数据源
         *
         * @param dataSourceProperties
         * @param shardingRuleConfiguration
         * @return
         * @throws SQLException
         */
        @Bean
        @Primary
        public DynamicDataSource dataSource(DataSourceProperties dataSourceProperties, ShardingRuleConfiguration shardingRuleConfiguration) throws SQLException {
            //初始化springboot数据源
            final DataSource dataSource = dataSourceProperties.initializeDataSourceBuilder().build();
    
            //设置动态数据源
            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();
    
            // 获取数据源对象
            final DataSource shardingDatasource = ShardingDataSourceFactory.createDataSource(ImmutableMap.of("ds0", dataSource),
                    shardingRuleConfiguration, new ConcurrentHashMap(), properties);
            return shardingDatasource;
        }
    
    }
    

    在业务项目中,你只需要配置ShardingRuleConfiguration即可开箱使用sharding了,例如

        /**
         * sharding分片规则
         *
         * @return
         */
        @Bean
        @Primary
        public ShardingRuleConfiguration shardingRuleConfiguration() {
            final ShardingRuleConfiguration shardingRuleConfiguration = new ShardingRuleConfiguration();
            TableRuleConfiguration sappPaperRankingTableRuleConfig = new TableRuleConfiguration();
            sappPaperRankingTableRuleConfig.setLogicTable("sapp_paper_ranking");
    
            //选需要分片的对应的库和表
            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()));
            // 配置分片规则
            shardingRuleConfiguration.getTableRuleConfigs().add(sappPaperRankingTableRuleConfig);
            return shardingRuleConfiguration;
        }
        
        
        /**
         * 精确分片算法,=与IN进行分片
         */
        public class SappPaperRankingPreciseShardingAlgorithm implements PreciseShardingAlgorithm<Integer> {
            @Override
            public String doSharding(Collection<String> tableNames/*表名*/, PreciseShardingValue<Integer> shardingValue /*分片键*/) {
        
                final Integer uid = shardingValue.getValue();
                
                /*省略*/
                
                throw new UnsupportedOperationException();
            }
        }
    
    

    相关文章

      网友评论

          本文标题:(springboot系列)springboot+shardin

          本文链接:https://www.haomeiwen.com/subject/bjwqmctx.html