• dynamic + shardingsphere(4.1.1) 实现动态分库分表


    复制代码
    1. 主要依赖:
    <dependency> <groupId>com.baomidou</groupId> <artifactId>dynamic-datasource-spring-boot-starter</artifactId> <version>3.3.2</version> </dependency> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-boot-starter</artifactId> <version>4.1.1</version> </dependency> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-namespace</artifactId> <version>4.1.1</version> </dependency>
    复制代码

    2. 数据库配置如下:

    复制代码
    spring.datasource.dynamic.primary=redisDB
    spring.datasource.dynamic.datasource.redisDB.driver-class-name = com.mysql.cj.jdbc.Driver
    spring.datasource.dynamic.datasource.redisDB.url=jdbc:mysql://10.95.35.103:3306/csc_siebel_api_call?characterEncoding=UTF-8&useUnicode=true&useSSL=false&serverTimezone=GMT
    spring.datasource.dynamic.datasource.redisDB.username=cscsitprd
    spring.datasource.dynamic.datasource.redisDB.password=Cscs23tpr#d
    spring.datasource.dynamic.datasource.campaignDB.driver-class-name = com.mysql.cj.jdbc.Driver
    spring.datasource.dynamic.datasource.campaignDB.url=jdbc:mysql://10.95.35.226:3306/CSC_MBHK_CAMPAIGN?characterEncoding=UTF-8&useUnicode=true&useSSL=false&serverTimezone=GMT
    spring.datasource.dynamic.datasource.campaignDB.username=cdcmbsit
    spring.datasource.dynamic.datasource.campaignDB.password=Cdcmb#sit123
    spring.datasource.dynamic.datasource.memberDB.driver-class-name = com.mysql.cj.jdbc.Driver
    spring.datasource.dynamic.datasource.memberDB.url=jdbc:mysql://10.95.35.226:3306/CSC_MBHK_MEMBER?characterEncoding=UTF-8&useUnicode=true&useSSL=false&serverTimezone=GMT
    spring.datasource.dynamic.datasource.memberDB.username=cdcmbsit
    spring.datasource.dynamic.datasource.memberDB.password=Cdcmb#sit123
    
    spring.shardingsphere.datasource.names=campaign-db
    spring.shardingsphere.datasource.campaign-db.type=com.alibaba.druid.pool.DruidDataSource
    spring.shardingsphere.datasource.campaign-db.driverClassName=com.mysql.jdbc.Driver
    spring.shardingsphere.datasource.campaign-db.url=${spring.datasource.dynamic.datasource.campaignDB.url}
    spring.shardingsphere.datasource.campaign-db.username=${spring.datasource.dynamic.datasource.campaignDB.username}
    spring.shardingsphere.datasource.campaign-db.password=${spring.datasource.dynamic.datasource.campaignDB.password}
    
    refreshCampaignContact.filterSwitch = true
    # 开启打印分表sql,生产要关闭false
    spring.shardingsphere.props.sql.show=true
    #分表
    spring.shardingsphere.sharding.tables.CUSTOMER_CAMPAIGN_CONTACT.actualDataNodes=campaign-db.CUSTOMER_CAMPAIGN_CONTACT_$->{0..63}
    # 分表字段 spring.shardingsphere.sharding.tables.CUSTOMER_CAMPAIGN_CONTACT.table-strategy.standard.sharding-column=CON_PER_ID
    # 实现分表规则类:-- HashModShardingAlgorithm spring.shardingsphere.sharding.tables.CUSTOMER_CAMPAIGN_CONTACT.table-strategy.standard.precise-algorithm-class-name=com.aswatson.conf.HashModShardingAlgorithm
    # 注释的是,表达式方法分表,但是我们要自己增加逻辑,所以做成实现分表规则类。 #spring.shardingsphere.sharding.tables.CUSTOMER_CAMPAIGN_CONTACT.tableStrategy.inline.shardingColumn=CON_PER_ID #spring.shardingsphere.sharding.tables.CUSTOMER_CAMPAIGN_CONTACT.tableStrategy.inline.algorithmExpression=CUSTOMER_CAMPAIGN_CONTACT_$->{(CON_PER_ID.hashCode()& Integer.MAX_VALUE) % 64} spring.shardingsphere.sharding.tables.CUSTOMER_LOY_CAM_SEG.actualDataNodes=campaign-db.CUSTOMER_LOY_CAM_SEG_$->{0..63} spring.shardingsphere.sharding.tables.CUSTOMER_LOY_CAM_SEG.table-strategy.standard.sharding-column=CONTACT_ID spring.shardingsphere.sharding.tables.CUSTOMER_LOY_CAM_SEG.table-strategy.standard.precise-algorithm-class-name=com.aswatson.conf.HashModShardingAlgorithm spring.datasource.dynamic.druid.initial-size = 5 spring.datasource.dynamic.druid.min-idle = 5 spring.datasource.dynamic.druid.max-active = 30 spring.datasource.dynamic.druid.max-wait = 6000 spring.datasource.dynamic.druid.time-between-eviction-runs-millis = 60000 spring.datasource.dynamic.druid.min-evictable-idle-time-millis = 300000 spring.datasource.dynamic.druid.validation-query = SELECT 1 FROM DUAL spring.datasource.dynamic.druid.test-while-idle = true spring.datasource.dynamic.druid.test-on-borrow = false spring.datasource.dynamic.druid.test-on-return = false
    复制代码

    3. 配置 ShardingDataSourceConfig类:

    复制代码
    package com.aswatson.conf;
    
    import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
    import com.baomidou.dynamic.datasource.provider.AbstractDataSourceProvider;
    import com.baomidou.dynamic.datasource.provider.DynamicDataSourceProvider;
    import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
    import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration;
    import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
    import org.apache.shardingsphere.shardingjdbc.spring.boot.SpringBootConfiguration;
    import org.springframework.boot.autoconfigure.AutoConfigureAfter;
    import org.springframework.boot.autoconfigure.AutoConfigureBefore;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Lazy;
    import org.springframework.context.annotation.Primary;
     
    import javax.annotation.Resource;
    import javax.sql.DataSource;
    import java.util.Map;
     
    @Configuration
    @AutoConfigureAfter({DynamicDataSourceAutoConfiguration.class, SpringBootConfiguration.class})
    public class ShardingDataSourceConfig {
    
        @Resource
        private DynamicDataSourceProperties properties;
    
        //@Lazy
        @Resource(name = "shardingDataSource")
        private DataSource shardingSphereDataSource;
    
       @Bean
    public DynamicDataSourceProvider dynamicDataSourceProvider() { Map<String, DataSourceProperty> datasourceMap = properties.getDatasource(); return new AbstractDataSourceProvider() { @Override public Map<String, DataSource> loadDataSources() { Map<String, DataSource> dataSourceMap = createDataSourceMap(datasourceMap);
              // @DS(campaign-db-sharding) 就是注入的数据源,分库分表的时候,在mapper层注入. dataSourceMap.put(
    "campaign-db-sharding", shardingSphereDataSource); return dataSourceMap; } }; } /** * 将动态数据源设置为首选的,当spring存在多个数据源时, 自动注入的是首选的对象设置为主要的数据源之后,就支持shardingjdbc原生的配置方式 */ @Primary @Bean public DataSource dataSource(DynamicDataSourceProvider dynamicDataSourceProvider) { DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource(); dataSource.setPrimary(properties.getPrimary()); dataSource.setStrict(properties.getStrict()); dataSource.setStrategy(properties.getStrategy()); dataSource.setProvider(dynamicDataSourceProvider); dataSource.setP6spy(properties.getP6spy()); dataSource.setSeata(properties.getSeata()); return dataSource; } }
    复制代码

    4. 配置分表的规则(简单精准分表策略):

    复制代码
    package com.aswatson.conf;
    
    import com.ctrip.framework.apollo.Config;
    import com.ctrip.framework.apollo.ConfigService;
    import java.util.Collection;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
    import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
    
    /**
     * @Author Tim
     * @Date 2022/6/30 11:52
     */
    @Slf4j
    public class HashModShardingAlgorithm implements PreciseShardingAlgorithm {
    
        // 通过Apollo client获取是否需要分表开关,不需要分表,通过availableTargetNames 截取 "_num"前的表
        public static String shardingTableSwitch = "sharding.table.switch";
        public static String nameSpace = "cdc-common";
    
        @Override
        public String doSharding(Collection availableTargetNames, PreciseShardingValue shardingValue) {
            Comparable value = shardingValue.getValue();
            int hashValue = value.hashCode();
            int availableTargetNamesLen = availableTargetNames.size();
            int targetNamesIdx = Math.abs(hashValue) % availableTargetNamesLen;
            Object[] availableTargetNamesArr = availableTargetNames.toArray(new Object[0]);
            String tableName = String.valueOf(availableTargetNamesArr[targetNamesIdx]);
            log.info("redisService-doSharding-tableName: {}", tableName);
            return getActualTable(tableName);
        }
    
        private String getActualTable(String tableName) {
            Config config = ConfigService.getConfig(nameSpace);
            boolean tableShardingSwitch = Boolean.parseBoolean(config.getProperty(shardingTableSwitch, "false"));
            if (!tableShardingSwitch) {
                String actualTable = tableName.replaceAll("\\d+","");
                return actualTable.substring(0, actualTable.length()-1);
            }
            log.info("redisService-getActualTable: tableShardingSwitch={}, tableName={}", tableShardingSwitch, tableName);
            return tableName;
        }
    
    }
    复制代码

    5.  分库分表使用,在mapper上增加注入的数据源名

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    package com.aswatson.infrastructure.dao.campaignDao.mapper;
     
    import com.aswatson.infrastructure.dao.campaignDao.model.CustomerCampaignContactPO;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import java.util.List;
    import org.apache.ibatis.annotations.Mapper;
    import org.apache.ibatis.annotations.Param;
    import org.apache.ibatis.annotations.Select;
     
    @Mapper
    @DS("campaign-db-sharding")
    public interface CustomerCampaignContactMapper extends BaseMapper<CustomerCampaignContactPO> {
     
        @Select("SELECT DISTINCT SEG_NUM FROM CUSTOMER_LOY_CAM_SEG WHERE CONTACT_ID = #{contactId}")
        List<String> getCustomerLoyCampaignSegments(@Param("contactId") String contactId);
     
        List<CustomerCampaignContactPO> getCustomerContactLoyByConPerIdAndFilter(@Param("contactId") String contactId);
     
    }

    6. 其他的数据源:

    复制代码
    package com.aswatson.infrastructure.dao.memberDao.mapper;
    
    import com.aswatson.infrastructure.dao.memberDao.model.CustomerLoyCardPO;
    import com.aswatson.infrastructure.dao.memberDao.model.CustomerLoyContactSplit1PO;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import java.util.List;
    import org.apache.ibatis.annotations.Mapper;
    import org.apache.ibatis.annotations.Param;
    
    /**
     * <p>
     *  Mapper 接口
     * </p>
     *
     * @author albert.yang
     * @since 2020-04-09
     */
    @Mapper
    @DS("memberDB")
    public interface CustomerLoyContactSplit1Mapper extends BaseMapper<CustomerLoyContactSplit1PO> {
    
        List<CustomerLoyCardPO> selectMobile(@Param("buId") String buId, @Param("mobile") String mobile,
            @Param("mobile2") String mobile2);
    }
    复制代码

    7. 注意的是,项目启动时候会报错:

    复制代码
    package com.aswatson;
    
    import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
    import io.micrometer.core.instrument.MeterRegistry;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.ImportResource;
    import org.springframework.scheduling.annotation.EnableScheduling;
    
    @Configuration
    //启动类要注意排除自动注入的数据源
    @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, DruidDataSourceAutoConfigure.class}, scanBasePackages = {"com.aswatson.*"})
    @ComponentScan({"com.aswatson.*"})
    @MapperScan("com.aswatson.infrastructure.dao.*")
    //@EnableDiscoveryClient
    @EnableScheduling
    public class RedisServerApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(RedisServerApplication.class, args);
        }
    
        @Bean MeterRegistryCustomizer<MeterRegistry> configurer(@Value("${spring.application.name}") String applicationName) {
            return registry -> registry.config().commonTags("application", applicationName);
        }
    
    }
    复制代码

     

     

    8. 写个测试接口就可以测试了:

     

  • 相关阅读:
    企业实践 | 国产操作系统之光? 银河麒麟KylinOS-V10(SP3)高级服务器操作系统基础安装篇
    Pandas用法入门学习(1)
    03【远程协作开发、TortoiseGit、IDEA绑定Git插件的使用】
    amlogic 机顶盒关闭DLNA 后,手机还能搜到盒子
    ES6中对象的扩展
    java中okhttp和httpclient那个效率高
    【三维目标检测】SASSD(一)
    C++学习——函数重载详解
    一款神器的 Python 工具,不写一行代码,就可以调用 Matplotlib 绘图
    “动捕设备+飞兔渲染软件”,激发数字人短视频营销新动力
  • 原文地址:https://www.cnblogs.com/lgg20/p/16473882.html