ShardSphere算法介绍(实现按年月日分片自定义算法)

内置算法

https://shardingsphere.apache.org/document/5.2.0/cn/user-manual/common-config/builtin-algorithm/sharding/
官网介绍已经很清楚了,但是官网的例子不多,下面是使用时间分片算法的具体例子:

Properties properties = new Properties();
//分片键的时间戳格式,必须遵循 Java DateTimeFormatter 的格式 识别数据
properties.setProperty("datetime-pattern", dateTimePattern);
//设置 起始时间 当前时间 2024-03-27 时间分片下界值,格式与 datetime-pattern 定义的时间戳格式一致
properties.setProperty("datetime-lower", dateTimeLower);
//设置 截止时间 
properties.setProperty("datetime-upper", dateTimeUpper);
//对应数据库表后缀名202211
properties.setProperty("sharding-suffix-pattern", suffixPattern);
//设置时间间隔
properties.setProperty("datetime-interval-unit", "MONTHS"); //MONTHS DAYS YEARS
//设置时间间隔数量
properties.setProperty("datetime-interval-amount", "1");
shardingAlgorithms.put(shardingAlgorithmName, new AlgorithmConfiguration("INTERVAL", properties));

自定义算法

自定义算法支持2种配置:
首先实现自定义算法类:

@Getter
@CommonsLog
@Component
public class HisDataMonthShardingAlgorithm implements StandardShardingAlgorithm<String> {

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

    private String suffixPattern;

    private ChronoUnit chronoUnit;

    /**
     * 在配置文件中配置算法的时候会配置 props 参数,框架会将props中的配置放在 properties 参数中,并且初始化算法的时候被调用
     *
     * @param properties properties
     */
    @Override
    public void init(Properties properties) {
        this.props = properties;
        String dateTimeLower = properties.getProperty("dateTimeLower");
        suffixPattern = properties.getProperty("suffixPattern");
        chronoUnit = ChronoUnit.valueOf(properties.getProperty("intervalUnit"));
        try {
            switch (chronoUnit) {
                case DAYS:
                    tableLowerDate = LocalDate.of(Integer.parseInt(dateTimeLower.split("-")[0]), Integer.parseInt(dateTimeLower.split("-")[1]), Integer.parseInt(dateTimeLower.split("-")[2]));
                    break;
                case MONTHS:
                    tableLowerDate = LocalDate.of(Integer.parseInt(dateTimeLower.split("-")[0]), Integer.parseInt(dateTimeLower.split("-")[1]), 1);
                    break;
                case YEARS:
                    tableLowerDate = LocalDate.of(Integer.parseInt(dateTimeLower), 1, 1);
                    break;
            }
        } catch (NumberFormatException e) {
            log.error("解析时间出错,返回当前时间", e);
            //解析出错,返回当前时间
            tableLowerDate = LocalDate.now();
        }
    }

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

    public  String getYYYYMM(String dateString) {
        LocalDate date = LocalDate.parse(dateString.split(" ")[0], DateTimeFormatter.ISO_LOCAL_DATE);
        return date.format(DateTimeFormatter.ofPattern(suffixPattern));
    }


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

        // 获取到范围查找的最大值,如果没有配置最大值,设置为当前 月
        LocalDate rangeUpperDate;
        if (shardingValue.getValueRange().hasUpperBound()) {
            rangeUpperDate = LocalDate.parse(shardingValue.getValueRange().upperEndpoint().split(" ")[0], DateTimeFormatter.ISO_LOCAL_DATE);
        } else {
            rangeUpperDate = LocalDate.now();
        }

        List<String> tableNames = new ArrayList<>();
        // 过滤那些存在的表
        while (rangeLowerDate.isBefore(rangeUpperDate) || rangeLowerDate.isEqual(rangeUpperDate)) {
            String actuallyTableName = shardingValue.getLogicTableName() + "_" + rangeLowerDate.format(DateTimeFormatter.ofPattern(suffixPattern));
            if (availableTargetNames.contains(actuallyTableName)) {
                tableNames.add(actuallyTableName);
            }
            rangeLowerDate = rangeLowerDate.plus(1, chronoUnit);
        }

        if (tableNames.isEmpty()) {
            log.warn("未匹配任何表");
            return availableTargetNames;
        }
        return tableNames;
    }


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

全限类名

// 自定义算法 使用全限类名
Properties properties = new Properties();
properties.setProperty("strategy","standard");
properties.setProperty("dateTimeLower",dateTimeLower);
properties.setProperty("algorithmClassName","com.antaiib.custom.sharding.util.HisDataMonthShardingAlgorithm");
shardingAlgorithms.put(shardingAlgorithmName, new AlgorithmConfiguration("CLASS_BASED", properties));

SPI

需要在resources目录下新建目录 META-INF\services,新建文件:
org.apache.shardingsphere.sharding.spi.ShardingAlgorithm
(为什么文件名是这个,因为自定义算法就是实现这个接口)
image.png
在文件中写入刚刚实现算法的全限类名:

com.example.sharding.util.HisDataMonthShardingAlgorithm

java API配置如下:

// 自定义算法 使用SPI
Properties properties = new Properties();
properties.setProperty("dateTimeLower", dateTimeLower);
properties.setProperty("intervalUnit", intervalUnit);
properties.setProperty("suffixPattern", suffixPattern);
shardingAlgorithms.put(shardingAlgorithmName, new AlgorithmConfiguration("HIS_DATA_SPI_BASED", properties));
  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ShardingSphere5.2是一个开源的分布式数据库中间件,可以用于在分布式系统中进行数据分片处理。在ShardingSphere5.2中,我们可以配置自定义分片算法实现自定义的数据分片策略。 首先,我们需要创建一个自定义分片算法类。这个类需要实现ShardingAlgorithm接口,并重写其中的方法。ShardingAlgorithm接口包含了分片算法的两个核心方法:doSharding和init。 在doSharding方法中,我们可以编写自己的分片逻辑。我们可以根据业务需求来判断数据应该分配到哪个分片上,然后返回对应的分片信息。在这个方法中,我们可以使用一些参数来获取到分片规则、分片键值和分片配置等信息。 在init方法中,我们可以进行一些初始化操作。比如,可以读取和解析配置文件,获取到分片的规则和配置信息,并进行一些初始化设置。 接下来,我们需要在ShardingSphere的配置文件中指定使用我们的自定义分片算法。我们可以在配置文件中通过配置项指定自定义分片算法的类名。同时,我们还需要配置其他相关的分片规则、分布式数据源等信息。 最后,我们将整个配置文件加载到ShardingSphere中,并启动分片功能。当系统需要进行数据分片时,ShardingSphere会自动调用我们的自定义分片算法来进行数据分片处理。 总结来说,ShardingSphere5.2配置自定义分片算法的步骤包括:创建自定义分片算法类并实现ShardingAlgorithm接口、编写自己的分片逻辑、在配置文件中指定自定义分片算法、加载配置文件到ShardingSphere并启动分片功能。通过这些步骤,我们就可以实现自定义的数据分片策略。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值