sharding分表应用笔记(二)——按时间分表策略配置

发布时间 2023-11-09 20:25:07作者: pjgyr

sharding分表应用笔记(二)——按时间分表策略配置

1 背景

应用背景:物理数据源只有一个;对于部分数据量大的表实行按月分表处理,其他的表仍然保持原先的模式不变。本篇记录sharding分表的时间分表策略配置。

环境:spring

2 配置

2.1 命名空间配置

<!-- 分表策略定义 -->
<bean id="datePreciseShardingAlgorithm" class="com.example.shardingDatePreciseShardingAlgorithm"></bean>
<bean id="dateRangeShardingAlgorithm" class="com.example.shardingDateRangeShardingAlgorithm"></bean>
<!-- 具体策略配置 -->
<sharding:standard-strategy id="byCreateTimeTableStrategy" sharding-column="create_time"precise-algorithm-ref="datePreciseShardingAlgorithm"range-algorithm-ref="dateRangeShardingAlgorithm"/>

(?)代表可缺省

<sharding:standard-strategy />

名称 类型 说明
id 属性 Spring Bean Id
sharding-column 属性 分片列名称
precise-algorithm-ref 属性 精确分片算法引用,用于=和IN。该类需实现PreciseShardingAlgorithm接口
range-algorithm-ref (?) 属性 范围分片算法引用,用于BETWEEN。该类需实现RangeShardingAlgorithm接口

其他未涉及的配置项请参考官方文档

2.2 策略接口实现

2.2.1 时间精确分片策略

/**
 * @author nagiumi
 * @date 2023/6/6
 * @description 精确分表算法
 */
public class DatePreciseShardingAlgorithm implements PreciseShardingAlgorithm<Date> {

    private static final Logger logger = LoggerFactory.getLogger(DatePreciseShardingAlgorithm.class);

    @Override
    public String doSharding(Collection<String> tableNames, PreciseShardingValue<Date> shardingValue) {
        Date date = shardingValue.getValue();
        String logicTableName = shardingValue.getLogicTableName();
        //ShardingUtils是一个自己创建的工具类,其中TABLE_SHARDING_START_TIME用于记录分表业务启动日期,用于实现原始表格的兼容
        if(ShardingUtils.TABLE_SHARDING_START_TIME.containsKey(logicTableName)) {
            // 查询时间在分表时间之前返回原表
            Date tableShardingStartTime = ShardingUtils.TABLE_SHARDING_START_TIME.get(logicTableName);
            if(date.before(tableShardingStartTime)) {
                return logicTableName;
            }
        }

        String suffix = "";
        try {
            //ShardingUtils是一个自己创建的工具类,其中getSuffixByYearMonth用于切分查询条件的年月信息,以确定合适的表节点
            suffix = ShardingUtils.getSuffixByYearMonth(date);
        } catch (Exception e) {
            logger.error("日期格式化异常,", e);
        }

        for (String key : tableNames) {
            if (key.endsWith(suffix)) {
                return key;
            }
        }
        throw new UnsupportedOperationException("不支持的分表字段");
    }
}

2.2.2 时间范围分片策略

/**
 * @author nagiumi
 * @date 2023/6/6
 * @description 范围分表算法
 */
public class DateRangeShardingAlgorithm implements RangeShardingAlgorithm<Date> {
    private final static Logger logger = LoggerFactory.getLogger(DateRangeShardingAlgorithm.class);

    @Override
    public Collection<String> doSharding(Collection availableTargetNames, RangeShardingValue rangeShardingValue) {
        List<String> list = new ArrayList<>();
        Range<Date> valueRange = rangeShardingValue.getValueRange();
        //必须有上下边界,便于确认分表节点,如果没有左边界则使用业务起始日期作为左边界;如果没有右边界以当前日期作为右边界
        Date lowerDate;
        try {
            lowerDate = valueRange.lowerEndpoint();
        } catch (IllegalStateException e) {
            lowerDate = DateUtil.getDate("2023-05-10");
            logger.error("日期格式化异常,", e);
        }

        Date upperDate = null;
        try {
            upperDate = valueRange.upperEndpoint();
        } catch (IllegalStateException e) {
            logger.error("日期格式化异常,", e);
        }
        if(Objects.isNull(upperDate)) {
            upperDate = new Date();
        }

        String logicTableName = rangeShardingValue.getLogicTableName();
        //ShardingUtils是一个自己创建的工具类,其中TABLE_SHARDING_START_TIME用于记录分表业务启动日期,用于实现原始表格的兼容
        if(ShardingUtils.TABLE_SHARDING_START_TIME.containsKey(logicTableName)) {
            // 查询时间在分表时间之前返回原表
            Date tableShardingStartTime = ShardingUtils.TABLE_SHARDING_START_TIME.get(logicTableName);
            if(lowerDate.before(tableShardingStartTime)) {
                list.add(logicTableName);
                lowerDate = tableShardingStartTime;
            }
        }

        //ShardingUtils是一个自己创建的工具类,其中getSuffixListForRange用于切分查询条件的年月信息(一个集合),以确定合适的表节点区间
        TreeSet<String> suffixSet = ShardingUtils.getSuffixListForRange(lowerDate, upperDate);
        for (String suffix : suffixSet) {
            String targetTableName = logicTableName + suffix;
            list.add(targetTableName);
        }
        return list;
    }
}

3 外部链接

ShardingSphere-4.1.1中文说明文档:https://shardingsphere.apache.org/document/4.1.1/cn/overview/