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/