当前位置:   article > 正文

Springboot + Mybatis Plus + ShardingSphere 5.1.0 实现多分片键自定义配置分表_shardingsphere5.1.0的分片算法

shardingsphere5.1.0的分片算法

前言

项目存储的数据量过多,所以需要对数据进行分表处理,以下只针对ShardingSphere插件的自定义配置操作

一、Maven依赖

    <dependency>
        <groupId>org.apache.shardingsphere</groupId>
        <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
        <version>5.1.0</version>
    </dependency>
    <!--sharding 5.1.0版本依赖tamcat-dbcp 10.0.16或者以上版本-->
    <dependency>
        <groupId>org.apache.tomcat</groupId>
        <artifactId>tomcat-dbcp</artifactId>
        <version>10.0.16</version>
    </dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

二、配置ymal文件(配置属性可以查看官方文档对于的版本)

官方地址:

https://shardingsphere.apache.org/document/5.1.0/cn/user-manual/shardingsphere-jdbc/spring-boot-starter/

自定义配置:(使用的pgsql数据库,所有的分表都需要提前建好,建议使用定时任务处理!!!)

spring:
  shardingsphere:
    #模式配置
    mode:
      #持久化仓库类型
      type: Standalone
      repository:
        type: File
      overwrite: true
    datasource:
      # 真实数据源名称,多个数据源用逗号区分
      names: yun
      # 配置第一个数据源
      yun:
        # 使用阿里的Druid连接池
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: org.postgresql.Driver
        url: jdbc:postgresql://127.0.0.1:3396/testSharding
        username: test
        password: test

      #其他数据库连接属性需要配置在datasource级别下!!!
      initial-size: 5
      min-idle: 5
      maxActive: 20
      # 配置获取连接等待超时的时间
      maxWait: 60000
      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
      timeBetweenEvictionRunsMillis: 60000
      # 配置一个连接在池中最小生存的时间,单位是毫秒
      minEvictableIdleTimeMillis: 300000
      # 打开PSCache,并且指定每个连接上PSCache的大小
      poolPreparedStatements: true
      maxPoolPreparedStatementPerConnectionSize: 20
      # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
      filters: stat,wall,slf4j
      # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
      connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
    rules:
      sharding:
        #分表策略
        tables:
          #表名
          test_info_tb:
            #通过行表达式匹配表名
            actual-data-nodes: yun.test_info_tb_$->{2023..2050}$->{['01','02','03','04','05','06','07','08','09','10','11','12']}_$->{0..19}
            table-strategy:
              complex:
                sharding-columns: id,create_time
                # 分布式序列算法名称
                sharding-algorithm-name: info
        #分片算法配置
        sharding-algorithms:
       	  # 前面自定义的分布式序列算法名称
          info:
            #类型使用自定义类型
            type: CLASS_BASED
            props:
              strategy: COMPLEX
              #填写全限定类名
              algorithmClassName: com.message.psmessageservice.sharding.SendTbComplexKeysShardingAlgorithm
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61

配置完成之后记得删除之前手动注入的Datasource依赖,同时在启动类下@SpringBootApplication的注解排除DruidDataSourceAutoConfigure类

	/*@Bean("DataSource")
    @ConfigurationProperties(prefix = "spring.datasource.yun")
    public DataSource druidDataSource(){
        return  new DruidDataSource();
    }*/
  • 1
  • 2
  • 3
  • 4
  • 5
@SpringBootApplication(exclude = {DruidDataSourceAutoConfigure.class})
  • 1

三、具体类的实现(通过继承对应的分片算法实现对应的接口类,这里采用的 多分片键的复合分片场景)

package com.message.psmessageservice.sharding;

import com.google.common.collect.Range;
import com.message.psmessageservice.utils.TimeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.sharding.api.sharding.complex.ComplexKeysShardingAlgorithm;
import org.apache.shardingsphere.sharding.api.sharding.complex.ComplexKeysShardingValue;
import java.util.*;

/**
 * @Author chenqian
 * @Description 自定义复合分表策略
 * @Date 2023-09-19 17:10
 * @Version 1.0
 */
@Slf4j
public class SendTbComplexKeysShardingAlgorithm implements ComplexKeysShardingAlgorithm<String> {


    @Override
    public Collection<String> doSharding(Collection<String> databaseNames, ComplexKeysShardingValue<String> complexKeysShardingValue) {
        // 得到每个分片健对应的值
        Collection<Object> timeValues = this.getShardingValue(complexKeysShardingValue, "create_time");
        Collection<Object> idValues = this.getShardingValue(complexKeysShardingValue, "id");

        List<String> shardingSuffix = new ArrayList<>();
        // 对时间按月处理,对user_id取模20处理
        for (Object id : idValues) {
            for (Object time : timeValues) {
                String date = TimeUtils.secondsToDateStr(Long.parseLong(time.toString()) * 1000, "yyyyMM");
                int num = id.hashCode() > 0 ? id.hashCode() : -id.hashCode();
                String suffix = "_" + date + "_" + num % 20;
                for (String databaseName : databaseNames) {
                    if (databaseName.endsWith(suffix)) {
                        shardingSuffix.add(databaseName);
                    }
                }
            }
        }
        return shardingSuffix;
    }

    private Collection<Object> getShardingValue(ComplexKeysShardingValue<String> shardingValues, final String key) {
        Collection<Object> valueSet = new ArrayList<>();
        Map<String, Collection<String>> columnNameAndShardingValuesMap = shardingValues.getColumnNameAndShardingValuesMap();
        if (columnNameAndShardingValuesMap.containsKey(key)) {
            valueSet.addAll(columnNameAndShardingValuesMap.get(key));
        }
        //自定义时间范围匹配表名
        Map<String, Range<String>> columnNameAndRangeValuesMap = shardingValues.getColumnNameAndRangeValuesMap();
        if (columnNameAndRangeValuesMap.containsKey(key)) {
            //时间范围默认查询半年
            Long startTime = System.currentTimeMillis() / 1000 - 6 * 30 * 86400;
            Long endTime = System.currentTimeMillis() / 1000;
            Range<String> endTimeRange = columnNameAndRangeValuesMap.get(key);
            if (endTimeRange.hasLowerBound()) {
                //取值采用Object类接收,再去做转换,因为会返回数据本身的包装类型,防止报错
                Object endpoint = endTimeRange.lowerEndpoint();
                startTime = Long.parseLong(String.valueOf(endpoint));
            }
            if (endTimeRange.hasUpperBound()) {
                Object upperBound =  endTimeRange.upperEndpoint();
                endTime = Long.parseLong(String.valueOf(upperBound));
            }
            valueSet.add(startTime);
            valueSet.add(endTime);
        }
        return valueSet;
    }

    @Override
    public void init() {

    }

    @Override
    public String getType() {
        return "INFO";
    }

    @Override
    public Properties getProps() {
        return ComplexKeysShardingAlgorithm.super.getProps();
    }

    @Override
    public void setProps(Properties props) {
        ComplexKeysShardingAlgorithm.super.setProps(props);
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91

最后

自定义代码不生效问题:在resouces/META-INF/services目录下创建一个org.apache.shardingsphere.sharding.spi.ShardingAlgorithm的文件名,写下自定义的全限定类名去覆盖源码中的文件从而生效。

在这里插入图片描述

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/756774
推荐阅读
相关标签
  

闽ICP备14008679号