ShardingSphere 5.2.1 版本使用

参考资料

ShardingSphere5.x.x(最新版)配置MySQL读写分离

shardingsphere按年月分库分表实战

ShardingSphere笔记(二):自定义分片算法 — 按月分表

Spring Boot集成ShardingSphere实现按月数据分片及创建自定义分片算法 | Spring Cloud 44

升级到ShardingSphere5后,原有的ShardingSphere4配置需要做出一些变更,这里特意记录一下方便其他有需要的朋友们快速切换。

我是一个从前端转过来,所以目前追求的是如何使用,至于原理可以看上面的参考资料,里面讲的比价详细。

一、pom依赖

升级前 ShardingSphere4需要添加的pom依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.16</version>
</dependency>
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    <version>4.1.1</version>
</dependency>

升级后ShardingSphere5需要添加的pom依赖

<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
    <version>5.2.1</version>
</dependency>
<!--
这里一定要设置yml版本,否则在shardingsphere 5.2 版本及以上会出现如下问题:
    "Correct the classpath of your application so that it contains a single, compatible version of org.apache.shardingsphere.infra.
    util.yaml.constructor.ShardingSphereYamlConstructor$1"

因为需要的解析yaml文件的库版本不满足框架要求,根据不同的springboot版本做出调整。

我这里使用的是springboot 2.6.8, 需要手动依赖`snakeyarml`并指定版本才可以。
如果你使用的是更高版本的springboot,pom文件中的properties位置调整yaml版本号即可。Springboot框架自带了这个框架,不需要重新引用

具体以你使用的springboot 版本为准进行调整就好了。
-->
<dependency>
    <groupId>org.yaml</groupId>
    <artifactId>snakeyaml</artifactId>
    <version>1.33</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

二、自定义分配算法

package com.study.config.shardingsphere;

import cn.hutool.core.date.DateUtil;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm;

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

/**
 * 按月分表的 Sharding 算法
 */
@Getter
@Slf4j
public class DataMonthShardingAlgorithm implements StandardShardingAlgorithm<Date> {

    private final ThreadLocal<SimpleDateFormat> formatThreadLocal = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyyMM"));

    private Properties props;
    /**
     * 设置该参数的原因是,如果在范围查找的时候我们没有设置最小值,比如下面的查询
     * where _time < '2023-09-01 00:00:00'
     * 这个时候范围查找就只有上限而没有下限,这时候就需要有一个下限值兜底,不能一致遍历下去
     */
    private Date tableLowerDate;

    /**
     * 在配置文件中配置算法的时候会配置 props 参数,框架会将props中的配置放在 properties 参数中,并且初始化算法的时候被调用
     *
     * @param properties properties
     */
    @Override
    public void init(Properties properties) {
        this.props = properties;
        String autoCreateTableLowerDate = properties.getProperty("auto-create-table-lower");
        try {
            this.tableLowerDate = formatThreadLocal.get().parse(autoCreateTableLowerDate);
        } catch (Exception e) {
            log.error("parse auto-create table lower date failed: {}, use default date 2023-09", e.getMessage());
            try {
                this.tableLowerDate = formatThreadLocal.get().parse("202309");
            } catch (ParseException ignored) {
            }
        }

    }

    /**
     * 精确路由算法
     *
     * @param availableTargetNames 可用的表列表(配置文件中配置的 actual-data-nodes会被解析成 列表被传递过来)
     * @param shardingValue        精确的值
     * @return 结果表
     */
    @Override
    public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Date> shardingValue) {
        Date value = shardingValue.getValue();
        // 根据精确值获取路由表
        String actuallyTableName = shardingValue.getLogicTableName() + shardingSuffix(value);
        if (availableTargetNames.contains(actuallyTableName)) {
            return actuallyTableName;
        }
        return null;
    }

    /**
     * 范围路由算法
     *
     * @param availableTargetNames 可用的表列表(配置文件中配置的 actual-data-nodes会被解析成 列表被传递过来)
     * @param shardingValue        值范围
     * @return 路由后的结果表
     */
    @Override
    public Collection<String> doSharding(Collection<String> availableTargetNames, RangeShardingValue<Date> shardingValue) {
        // 获取到范围查找的最小值,如果条件中没有最小值设置为 tableLowerDate
        Date rangeLowerDate;
        if (shardingValue.getValueRange().hasLowerBound()) {
            rangeLowerDate = shardingValue.getValueRange().lowerEndpoint();
        } else {
            rangeLowerDate = tableLowerDate;
        }

        // 获取到范围查找的最大值,如果没有配置最大值,设置为当前时间 + 1 月
        // 这里需要注意,你的项目里面这样做是否合理
        Date rangeUpperDate;
        if (shardingValue.getValueRange().hasUpperBound()) {
            rangeUpperDate = shardingValue.getValueRange().upperEndpoint();
        } else {
            // 往后延一个月
            rangeUpperDate = DateUtil.offsetMonth(new Date(), 1);
        }
        rangeUpperDate = DateUtil.endOfMonth(rangeUpperDate);
        List<String> tableNames = new ArrayList<>();
        // 过滤那些存在的表
        while (rangeLowerDate.before(rangeUpperDate)) {
            String actuallyTableName = shardingValue.getLogicTableName() + shardingSuffix(rangeLowerDate);
            if (availableTargetNames.contains(actuallyTableName)) {
                tableNames.add(actuallyTableName);
            }
            rangeLowerDate = DateUtil.offsetMonth(rangeLowerDate, 1);
        }
        return tableNames;
    }

    /**
     * sharding 表后缀 _yyyyMM
     */
    private String shardingSuffix(Date shardingValue) {
        return "_" + formatThreadLocal.get().format(shardingValue);
    }

    /**
     * SPI方式的 SPI名称,配置文件中配置的时候需要用到
     */
    @Override
    public String getType() {
        return "HIS_DATA_SPI_BASED";
    }
}

三、注册算法

这里我们采用SPI的方式将自定义算法注册到ShardingSphere。

首先需要在 resources 文件夹下创建文件夹 META-INF/services。然后在该文件夹下创建文件,
文件名为org.apache.shardingsphere.sharding.spi.ShardingAlgorithm,这个文件名不能随意修改,否则无法注册成功, 文件内写上我们自定义的分片算法类全路径,也就是上面的com.study.config.shardingsphere.DataMonthShardingAlgorithm

四、yml配置文件

升级前 ShardingSphere4需要添加的数据库配置, ShardingSphere4 我没有做过按月分表,还是使用的根据id取模分表,后面需要做按月分表了才升级到了ShardingSphere5。

spring:
  shardingsphere:
    props:
      sql:
        show: false
    datasource:
      type: com.alibaba.druid.pool.DruidDataSource
      names: db-0
      db-0:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        username: root
        password: root
        url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2b8&rewriteBatchedStatements=true
    sharding:
      default-data-source-name: db-0
      tables:
        person_sync_record:
          actual-data-nodes: db-0.person_sync_record_$->{0..15}
          key-generator:
            column: equipment_id
            type: SNOWFLAKE
          table-strategy:
            inline:
              sharding-column: equipment_id
              algorithmExpression: person_sync_record_$->{equipment_id % 16}
        track_record:
          actual-data-nodes: db-0.track_record_$->{0..1}
          key-generator:
            column: id
            type: SNOWFLAKE
          table-strategy:
            inline:
              sharding-column: id
              algorithmExpression: track_record_$->{id % 2}

升级前 ShardingSphere5需要添加的数据库配置

spring:
  shardingsphere:
    props:
      sql:
        show: false
    datasource:
      names: db-0
      db-0:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        username: root
        password: root
        url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2b8&rewriteBatchedStatements=true
    rules:
      sharding:
        tables:
          person_sync_record:
            actual-data-nodes: db-0.person_sync_record_$->{0..15}
            key-generator:
              column: id
              type: SNOWFLAKE
            table-strategy:
              standard:
                sharding-column: id
                sharding-algorithm-name: person_sync_record_inline
          track_record:
            # 表的真实表列表(需要注意这里的表都应该存在,否则就有可能出现 NPE 异常)
            actual-data-nodes: db-0.track_record_202309, db-0.track_record_2023${10..12}, db-0.track_record_20240${1..9}, db-0.track_record_2024${10..12}
            key-generator:
              column: id
              type: SNOWFLAKE
            # 分片策略配置
            table-strategy:
              standard:
                # 分片算法是 his_month_sharding, 这个名称是在下面配置的
                sharding-algorithm-name: his_month_sharding
                # 分片列是 trace_time, 需要注意的是,分表算法的数据类型一定要和这个分片的列数据类型一致
                sharding-column: trace_time
        # 配置分片算法
        sharding-algorithms:
          person_sync_record_inline:
            type: INLINE
            props:
              algorithm-expression: person_sync_record_$->{id % 16}
          # 分片算法名称
          his_month_sharding:
            # 分片算法类型,这个type是我们的分片算法实现类中 getType()的返回值,SPI适用于这种方式
            type: HIS_DATA_SPI_BASED

五、测试

运行项目,对两个表分别插入数据,然后进行查询发现数据正常。这里需要注意的是按月分表的 数据表进行查询的时候一定要带上 时间,否则无法确定你需要查询的分表是哪些。

  • 18
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ShardingSphere 5.2.1是一个开源的分布式数据库中间件,它能够对关系型数据库进行分片和分表操作,提供了数据分片、读写分离、分布式事务等功能。 ShardingSphere 5.2.1的主要特点有: 1. 数据分片:能够将单一的数据库拆分成多个片段,使得数据在多个数据库中进行存储和查询,从而提高数据库的并发处理能力。 2. 读写分离:支持将读操作和写操作分别分发到不同的数据库节点上,进行负载均衡和提升读写性能。 3. 分布式事务:通过协调多个数据库节点进行事务的提交和回滚,保证分布式环境下的一致性。 4. 数据融合:支持将多个数据库中的数据进行合并查询,并提供了跨库查询的能力。 5. 水平扩展:通过增加数据库节点,实现对系统的水平扩展,提高系统的吞吐量和扩展能力。 6. 透明化接入:通过简单的配置,可以将ShardingSphere作为中间件接入到已有的系统中,无需对现有代码进行修改。 ShardingSphere 5.2.1提供了丰富的功能和灵活的配置选项,可以根据实际需求进行选择和配置。同时,它还提供了基于Spring和MyBatis的开箱即用的集成工具,方便开发人员进行使用。 总之,ShardingSphere 5.2.1是一个功能强大且易于使用的分布式数据库中间件,适用于各种规模的应用程序,能够帮助用户解决数据库性能瓶颈和扩展性等问题,提升系统的处理能力和性能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值