分库分表神器 Sharding-JDBC(按天分表案例)

  • Post author:
  • Post category:其他





配置手册 :: ShardingSphere


icon-default.png?t=M4AD
https://shardingsphere.apache.org/document/legacy/4.x/document/cn/manual/sharding-jdbc/configuration/



shardingsphere官方文档。今天我们用shardingJDBC做按天分表

依赖

<!-- 分表 -->
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    <version>4.1.1</version>
</dependency>

配置

根据配置手册一点点配置连接数据库,然后做入库规则。

// 配置数据源以及数据库连接池
//因为我使用得是HikariDataSource,所以url使用的是spring.shardingsphere.datasource.master.jdbc-url,其他的我还没试过
//type是一定要配置的
spring.shardingsphere.datasource.names=master
spring.shardingsphere.datasource.master.jdbc-url=jdbc:mysql://localhost:3306/数据库?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
spring.shardingsphere.datasource.master.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.master.username=账号
spring.shardingsphere.datasource.master.password=密码
spring.shardingsphere.datasource.master.type=com.zaxxer.hikari.HikariDataSource
//数据库节点,入哪几个数据库,这里我们暂且这么写,因为后边我们需要动态更新
spring.shardingsphere.sharding.tables.表名.actual-data-nodes=master.表名$->{20220604..20220605}
//根据哪个字段判断入表
spring.shardingsphere.sharding.tables.表名.table-strategy.standard.sharding-column=create_time
//指定分表算法策略的类(自定义的类)
spring.shardingsphere.sharding.tables.表名.table-strategy.standard.precise-algorithm-class-name=com.lt.config.DateAlgorithm
// 主键
spring.shardingsphere.sharding.tables.表名.key-generator.column=id
// 主键策略
spring.shardingsphere.sharding.tables.表名.key-generator.type=SNOWFLAKE
// 表名不加后缀
spring.shardingsphere.sharding.binding-tables=表名

注意上边我们自定义了分表算法策略,也就是这个配置

spring.shardingsphere.sharding.tables.表名.table-strategy.standard.precise-algorithm-class-name=com.lt.config.DateAlgorithm

这个类主要是为了让我们自定义分表策略。但是前提是,我们需要拿到全部的表,才能用策略去入表。现在我们的配置是

spring.shardingsphere.sharding.tables.表名.actual-data-nodes=master.表名$->{20220604..20220605}

这里只配置了两个表,那肯定是远远不够的。那么,现在我们就要考虑如何去拿到全部的表。我的做法是:新增一个表,去管理分表。类似于

把表名都交给mangage去管理。当我们查询mangage表的时候就可以看到全部表名。(建表是需要自己的定时任务去建表)

接下来我们就要把拿到的表名全部注入到框架扫描类的属性节点(SpringBootShardingRuleConfigurationProperties)里。

    private final SpringBootShardingRuleConfigurationProperties shardingRuleConfigurationProperties;

    private final MangageMapper mangageMapper;
    public static SpringBootShardingRuleConfigurationProperties cloneRuleConfigurationProperties = null;
    @PostConstruct
    public void initDataNodes(){
        // 检查今天明天的表是否存在(自定义方法,自己想怎么检查怎么检查)
        checkTableExist();
        // 加载mangage表获取都有哪些天的表
        List<Mangage> list = mangage.selectList(null);
        // 拿到所有后缀。Suffix是Mangage表的一个属性
        List<Integer> suffixList = list.stream().map(Mangage::getSuffix).collect(Collectors.toList());
        // 动态注入扩展节点到shardingRuleConfigurationProperties
        Map<String, YamlTableRuleConfiguration> tables = shardingRuleConfigurationProperties.getTables();
        YamlTableRuleConfiguration table = tables.get("表名");
        // 组装属性
        StringBuilder stringBuilder = new StringBuilder("master.表名$->{");
        for (int i = 0; i < suffixList.size(); i++) {
            stringBuilder.append(suffixList.get(i));
            if (i==suffixList.size()-1){
                stringBuilder.append("}");
            }else {
                stringBuilder.append(",");
            }
        }

        // 事例master.表名$->{20220604,20220605,20220606}
        table.setActualDataNodes(stringBuilder.toString());
        // cloneRuleConfigurationProperties供全局查看使用
        cloneRuleConfigurationProperties = shardingRuleConfigurationProperties;
    }

这样就有了所有表名。然后我们配置我们自定义的路由规则。target就是路由的表的全名

public class DateAlgorithm implements PreciseShardingAlgorithm {

    @Override
    // 简单说就是拿到所有分表,然后根据preciseShardingValue去自定义匹配想入哪个表
    public String doSharding(Collection collection, PreciseShardingValue preciseShardingValue) {
        // 获取全部表路由
        ArrayList<String> list = new ArrayList<>();
        Map<String, YamlTableRuleConfiguration> tables = 
                cloneRuleConfigurationProperties.getTables();
        YamlTableRuleConfiguration table = tables.get("表名");
        String logicTable = table.getLogicTable();
        String nodes = table.getActualDataNodes();
        int il = nodes.lastIndexOf("{");
        String substringNodes = nodes.substring(il+1, nodes.length() - 1);
        String[] splitNodes = substringNodes.split(",");
        for (int i = 0; i < splitNodes.length; i++) {
            list.add(logicTable+splitNodes[i]);
        }
        // 匹配路由,返回路由表表名
        String suffix = null;
        if (preciseShardingValue.getValue() instanceof Date){
            Date value =(Date) preciseShardingValue.getValue();
            suffix = new SimpleDateFormat("yyyyMMdd").format(value);
        }else {
            String value =(String) preciseShardingValue.getValue();
            suffix = value.split("T")[0].replace("-", "");
        }
        String target = null;
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i).contains(suffix)){
                target = list.get(i);
                break;
            }
        }
        return target;
    }

}

最后,之前我们需要拿到全部的表。但是表每天都有新的创建,所以我们在创建表之后立即去更新获取我们全部的表即可。

以上仅为我个人使用的理解。用法或许不规范,请指出。



版权声明:本文为wai_58934原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。