Sharding-JDBC动态分表实现

Sharding-JDBC动态水平分表实现

背景:

  • 在项目中遇到了按照日期动态水平分表的需求,系统属于监控系统,每10分钟保存一次监控数据,并且每次要采集200个节点上的数据,即每次采集数据(间隔10分钟),向数据表添加200条记录,这样一个月数据表就有将近100万条记录。
  • 为了控制单表数据量,并且为了方便后期数据统计,所以,每个月创建一张新表,之后的采集数据都写到新表中,例如报警信息表:alarm_histrtory表,按照日期水平分表alarm_histrtory201912,alarm_histrtory202001,alarm_histrtory202002,分别代表2019年12月、2020年1月、2020年2月的数据表。
  • 每个月都需要创建一张新的数据表,但是Sharding-JDBC水平分表不能动态变化,所以,为了实现Sharding-JDBC的水平分表配置随着时间,动态修改,而无需程序重启。
  • 示例代码:https://github.com/xujingle1995/sharding-jdbc

解决方案:

方案一:
通过配置中心,修改配置文件,然后sharding-jdbc自动获取新的分库分表配置,从而实现动态修改。这个方案还是需要人的介入,如果需要了解这种方案,只需要springboot中引入nacos配置中心即可。如果nacos不会配置可以参考:
1.官方文档:https://github.com/alibaba/spring-cloud-alibaba/wiki/Nacos-config
2.相关博客:https://blog.csdn.net/qq_26932225/article/details/86536837、https://blog.csdn.net/qq_26932225/article/details/86548829
方案二:
只需要以下三步:
1.自定义分片算法类
2.添加spring定时任务,动态修改Sharding-JDBC的配置。
3.配置application.properties配置文件

开始实践

1.准备工作:
  • 创建Springboot工程,pom.xml引入mysql、mybatis、sharding-jdbc依赖
  • 创建数据库:见本文最后的SQL语句
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.2</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- sharding-jdbc依赖 -->
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
            <version>4.0.0-RC1</version>
        </dependency>
  </dependencies>
2.自定义分片算法类(重要)

自定义分片算法类,用于当SQL语句中包含了分片键,sharding-jdbc会调用该类的doSharding方法,得到要查询的实际数据表名我这里自定义乐standard的精确分片和范围分片:

package com.xjl.sharding.config;

import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;

import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;

/**
 * @Title: dongfangdianqi
 * @description: alarmHistory 精确分片 = in
 * @create: 2020-02-25 14:12
 * @update: 2020-02-25 14:12
 * @updateRemark: 修改内容
 * @Version: 1.0
 */
@Slf4j
public class PreciseSharingTableAlgorithmOfAlarmhis implements PreciseShardingAlgorithm<Date> {
   
    private SimpleDateFormat dateformat = new SimpleDateFormat("yyyyMM");
    @Override
    public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Date> shardingValue) {
   

        StringBuffer tableName = new StringBuffer();

        log.info("执行操作的表名{}",shardingValue.getLogicTableName() + dateformat.format(shardingValue.getValue()));

        tableName.append(shardingValue.getLogicTableName()).append(dateformat.format(shardingValue.getValue()));
        return tableName.toString();
    }
}
package com.xjl.sharding.config;

import com.google.common.collect.Lists;
import com.google.common.collect.Range;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingValue;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Title: dongfangdianqi
 * @description: 根据发生时间的范围查询分片算法 between and
 * @create: 2020-02-25 16:55
 * @update: 2020-02-25 16:55
 * @updateRemark: 修改内容
 * @Version: 1.0
 */
@Slf4j
public class RangeShardingAlgorithmOfAlarmhis implements RangeShardingAlgorithm<Date> {
   

    private static SimpleDateFormat dateformat = new SimpleDateFormat("yyyyMM");

    @Override
    public Collection<String> doSharding(Collection<String> availableTargetNames, RangeShardingValue<Date> shardingValue) {
   
        Collection<String> result = new LinkedHashSet<>();

        Range<Date> shardingKey = shardingValue.getValueRange();

        // 获取起始,终止时间范围
        Date startTime = shardingKey.lowerEndpoint();
        Date endTime = shardingKey.upperEndpoint();
        Date now = new Date();
        if (startTime.after(now)){
   
            startTime = now;
        }
        if (endTime.after(now)){
   
            endTime = now;
        }
        Collection<String> tables = getRoutTable(shardingValue.getLogicTableName(), startTime, endTime);

        if (tables != null && tables.size() >0</
  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值