sharding-jdbc 的 RangeShardingAlgorithm 怎么用?

发布于 2022-09-11 22:14:03 字数 310 浏览 24 评论 0

sharding-jdbc 的 RangeShardingAlgorithm 怎么用?
https://segmentfault.com/a/11... 对于这篇文章
有2点我不是很明白,请指点一下。
在我的想象中:PreciseShardingAlgorithm 和 RangeShardingAlgorithm 应该是二选一。文中和官方说 RangeShardingAlgorithm 是可选。(我第一直觉 RangeShardingAlgorithm 应该是按范围分片

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

时光礼记 2022-09-18 22:14:03

以下个人理解,可能有不对之处,欢迎讨论。
(1)精确分片 和 范围分片
PreciseShardingAlgorithm 要求是必选的,RangeShardingAlgorithm 是可选的。也就是你如果使用 RangeShardingAlgorithm 分片,也要必须实现 PreciseShardingAlgorithm 精确分片。

PreciseShardingAlgorithm 只支持 = in 的操作,RangeShardingAlgorithm 只支持 BETWEEN AND, >, <, >=, <= 操作。
范围分片,应该比较适合对一定范围的数据的处理,能避免对更多的库和表进行sql执行。
精确分片,应该比较适合没有范围的数据处理,也就是你说的主键求余。

(2)行表达式
官方说明:
行表达式,使用Groovy的表达式,提供对SQL语句中的=和IN的分片操作支持,只支持单分片键。对于简单的分片算法,可以通过简单的配置使用,从而避免繁琐的Java代码开发,如: t_user_$->{u_id % 8} 表示t_user表根据u_id模8,而分成8张表,表名称为t_user_0t_user_7

所以复杂的分片算法,可以通过java配置来实现
下面这个就是 范围分片的一个实现, 基于 sharding-jdbc 4 版本
github: 代码地址

package fun.gengzi.codecopy.business.subdata.strategy.range;

import cn.hutool.core.date.DateUtil;
import com.google.common.collect.Range;
import fun.gengzi.codecopy.business.subdata.strategy.precise.InDateShardingStrategyConfiguration;
import org.apache.commons.lang3.StringUtils;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.Date;
import java.util.LinkedHashSet;

/**
 * <h1>范围值控制分库分表</h1>
 *
 * @author gengzi
 * @date 2020年7月2日11:07:15
 */
public class InMonthDataBaseRangeShardingConfiguration implements PreciseShardingAlgorithm<Date>, RangeShardingAlgorithm<Date> {

    private Logger logger = LoggerFactory.getLogger(InDateShardingStrategyConfiguration.class);

    public InMonthDataBaseRangeShardingConfiguration() {
        logger.info("初始化 -> [{}]", "InMonthDataBaseRangeShardingConfiguration ----- 根据月份范围分片算法-启用");
    }

    /**
     * Sharding.
     *
     * @param availableTargetNames available data sources or tables's names
     * @param shardingValue        sharding value
     * @return sharding results for data sources or tables's names
     */
    @Override
    public Collection<String> doSharding(Collection<String> availableTargetNames, RangeShardingValue<Date> shardingValue) {
        Collection<String> result = new LinkedHashSet<>(availableTargetNames.size());
        Range<Date> range = shardingValue.getValueRange();

        Date lowerDate = range.lowerEndpoint();
        Date upperDate = range.upperEndpoint();

        logger.info("lowerDate : {} ", DateUtil.formatDateTime(lowerDate));
        logger.info("upperDate : {} ", DateUtil.formatDateTime(upperDate));

        Integer low = Integer.valueOf(DateUtil.format(lowerDate, "MM"));
        Integer upper = Integer.valueOf(DateUtil.format(upperDate, "MM"));


        for (int i = low; i <= upper; i++) {
            for (String each : availableTargetNames) {
                if (each.endsWith(i + "")) {
                    result.add(each);
                }
            }
        }
        return result;
    }

    /**
     * Sharding.
     *
     * @param availableTargetNames available data sources or tables's names
     * @param shardingValue        sharding value
     * @return sharding result for data source or table's name
     */
    @Override
    public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Date> shardingValue) {
        // shardingValue 分片的值 日期,2020-06-06 15:12:00  根据年份分表,获取年份最小的,扩展年份最大的
        // 假如只扩展两年的 2020  2021。
        //配置的分片的sharding-column对应的值
        Date timeValue = shardingValue.getValue();
        String time = DateUtil.formatDate(timeValue);
        logger.info("time: {}",time);
        //分库时配置的sharding-column
        String timeColumn = shardingValue.getColumnName();
        //需要分库的逻辑表
        String tableName = shardingValue.getLogicTableName();
        logger.info("分表策略: 分片值 : {} , 分片列: {} , 逻辑表: {} ", time, timeColumn, tableName);
        availableTargetNames.forEach(name->{
            logger.info("availableTargetName :{} ", name);
        });
        //按年路由
        for (String each : availableTargetNames) {
            String value = StringUtils.substring(time, 5, 7);
            if (each.endsWith(Integer.parseInt(value)+"")) {
                return each;
            }
        }
        throw new UnsupportedOperationException();
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文