Java   发布时间:2022-04-02  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了在多数据源中对部分数据表使用shardingsphere进行分库分表大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

背景

近期在项目中需要使用多数据源,其中有一些表的数据量比较大,需要对其进行分库分表;而其他数据表数据量比较正常,单表就可以。
项目中可能使用其他组的数据源数据,因此需要多数据源支持。
经过调研多数据源配置比较方便。在该项目中分库分表的策略比较简单,仅根据一个字段分就可以,因此分库分表方案选用比较流行方便易用的 sharding-jdbc
需要实现的目标是 根据学生姓名字段 student_name 进行分表,但是不需要分库。数据表是student_hist0 - student_hist9

引入 sharding-jdbc maven 依赖

<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-core</artifactId>
    <version>4.1.1</version>
</dependency>

数据源配置文件

spring:
  application:
    name: student-service-provider
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8
    defaultPropertyInclusion: non_null
    deserialization:
      FAIL_ON_UNKNOWN_PROPERTIES: false 
  #对返回的时间进行格式化
  datasource:
    hikari:
      student:
        url: jdbc:mysql://127.0.0.1:3306/student_service?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&useTimezone=true&serverTimezone=GMT%2
        username: root
        password: root123
      log1:
        url: jdbc:mysql://127.0.0.1:3306/log1?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false
        username: root
        password: root123
      log2:
        url: jdbc:mysql://127.0.0.1:3306/log2?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false
        username: root
        password: root123

配置多数据源代码

DatasourceProperties 数据源

import com.zaxxer.hikari.HikariDatasource;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.Annotation.Configuration;

@Data
@Configuration
@ConfigurationProperties(prefix = "spring.datasource.hikari")
public class DatasourceProperties {

    private HikariDatasource student;
	private HikariDatasource log1;
	private HikariDatasource log2;

}

DynamicDatasource 动态数据源

import org.springframework.jdbc.datasource.lookup.AbstractRoutIngDatasource;

public class DynamicDatasource extends AbstractRoutIngDatasource {

    /*
    当前据源名称
     */
    private static final ThreadLocal<String> datasourceContextHolder = new ThreadLocal<>();

    /*
    设置数据源名称
     */
    public static void setDatasourcename(String datasourceName) {
        datasourceContextHolder.set(datasourceName);
    }

    /*
    获取据源名称
     */
    public static String getDatasourcename() {
        return datasourceContextHolder.get();
    }

    /*
    清除当数据源名称
     */
    public static void clearDatasource() {
        datasourceContextHolder.remove();
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return getDatasourcename();
    }
}
@H_471_2@multiDatasource 多数据源标记

import java.lang.Annotation.ElementType;
import java.lang.Annotation.Retention;
import java.lang.Annotation.RetentionPolicy;
import java.lang.Annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface MultiDatasource {
    String value() default DatasourceConfig.DEFAULT_DATAsourcE_NAME;
}

重点来了,因为是根据表的某一个字段进行分表,该字段是一个字符串类型,因此需要想根据字符串的一致性hash码算出在哪张表上。在sharding-jdbc需要实现 PreciseShardingAlgorithm 类
例如:想要在student.student_hist 表中根据学生姓名进行分表,逻辑表是student_hist,真实表是 student_hist0 - student_hist9
DatasourceConfig.SHARD_MMS_DATAsourcE_TABLE_COUNT=10

import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
import java.util.Collection;

public class PreciseNodEIDShardingAlgorithm implements PreciseShardingAlgorithm<String> {

    @Override
    public String doSharding(Collection<String> collection, PreciseShardingValue<String> preciseShardingvalue) {
        for (String tbnm : collection) {
            if (tbnm.endsWith("hist" + (getHash(preciseShardingValue.getValue()) % DatasourceConfig.SHARD_MMS_DATAsourcE_TABLE_COUNT))) {
                return tbnm;
            }
        }
        throw new UnsupportedoperationException();
    }
	
	private static int getHash(String str) {
        final int p = 16777619;
        int hash = (int) 2166136261L;
        for (int i = 0; i < str.length(); i++)
            hash = (hash ^ str.charAt(i)) * p;
        hash += hash << 13;
        hash ^= hash >> 7;
        hash += hash << 3;
        hash ^= hash >> 17;
        hash += hash << 5;
 
        // 如果算出来的值为负数则取其绝对值
        if (hash < 0)
            hash = Math.abs(hash);
        return hash;
    }
}

多数据源装配 DatasourceConfig 。需要指定默认数据源,当不需要使用 分表的表时就使用默认的数据源,否则指定需要分表的数据源。
在配置分表策略时如果不需要分库,可以不进行设置 tableRuleConfiguration.setDatabaseShardingStrategyConfig();

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.shardingjdbc.api.ShardingDatasourceFactory;
import org.springframework.beans.factory.Annotation.Autowired;
import org.springframework.context.Annotation.bean;
import org.springframework.context.Annotation.Configuration;
import org.springframework.context.Annotation.PriMary;
import org.springframework.jdbc.datasource.DatasourcetransactionManager;
import org.springframework.transaction.PlatformtransactionManager;

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

@Configuration
public class DatasourceConfig {

    public static final String DEFAULT_DATAsourcE_NAME = "defaultDatasource";
    public static final String MMS_DATAsourcE_NAME = "mmsDatasource";
    public static final String SHARD_MMS_DATAsourcE_NAME = "shardMmsDatasource";

    public static int SHARD_MMS_DATAsourcE_TABLE_COUNT = 10;

    @Autowired
    private DatasourceProperties properties;

    @PriMary
    @Bean(name = "dynamicDatasource")
    public Datasource dynamicDatasource() {
        DynamicDatasource dynamicDatasource = new DynamicDatasource();
        // 默认数据源
        dynamicDatasource.setDefaultTargetDatasource(properties.getMms());
        // 配置多数据源
        Map<Object, Object> dsmap = new HashMap();
        dsmap.put(DEFAULT_DATAsourcE_NAME, properties.getstudent());
        dsmap.put(MMS_DATAsourcE_NAME, properties.getstudent());
        dsmap.put(SHARD_MMS_DATAsourcE_NAME, buildShardDatasources());
        dynamicDatasource.setTargetDatasources(dsmap);
        return dynamicDatasource;
    }

    public Datasource buildShardDatasources() {
        // 配置多数据源
        Map<String, Datasource> dsmap = new HashMap();
        dsmap.put("shardMms", properties.getMms());
        TableRuleConfiguration stuHisTableRuleConfig = new TableRuleConfiguration("student_hist", "shardMms.student_hist${0.." + (SHARD_MMS_DATAsourcE_TABLE_COUNT - 1) + "}");
//        tableRuleConfiguration.setDatabaseShardingStrategyConfig();
        stuHisTableRuleConfig.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("student_name", new PreciseNodEIDShardingAlgorithm()));

        ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
        shardingRuleConfig.getTableRuleConfigs().add(stuHisTableRuleConfig);
        try {
            Properties properties = new Properties();
            properties.setProperty("sql.show", "true");
            return ShardingDatasourceFactory.createDatasource(dsmap, shardingRuleConfig, properties);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
            throw new IllegalArgumentexception();
        }
    }

    @Bean
    public PlatformtransactionManager transactionManager() {
        return new DatasourcetransactionManager(dynamicDatasource());
    }

}

多数据源切换 DatasourceAspect ,需要使用多数据源切换时,需要在service方法上使用标注方法 MultiDatasource 并指定数据源。

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Annotation.Around;
import org.aspectj.lang.Annotation.Aspect;
import org.aspectj.lang.Annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.Annotation.Configuration;
import org.springframework.core.Annotation.order;
import java.lang.reflect.Method;

@Aspect
@Configuration
@Slf4j
@Order(1)
public class DatasourceAspect {

    //切入点,service 中所有注解方法
    @Pointcut("execution(* com.huitong..service..*.*(..)) && @Annotation(com.huitong.app.config.datasource.MultiDatasourcE)")
    public void datasourceAspect() {
    }

    @Around("datasourceAspect()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignaturE) joinPoint.getSignature();
        Method method = signature.getMethod();
        MultiDatasource ds = method.getAnnotation(MultiDatasource.class);
        if (ds != null) {
            DynamicDatasource.setDatasourcename(ds.value());
        }
        try {
            return joinPoint.proceed();
        } finally {
            DynamicDatasource.clearDatasource();
        }
    }
}

文献:

大佬总结

以上是大佬教程为你收集整理的在多数据源中对部分数据表使用shardingsphere进行分库分表全部内容,希望文章能够帮你解决在多数据源中对部分数据表使用shardingsphere进行分库分表所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签: