栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

sharding sphere 4.0.0-RC1版本 按年分表(后续优化)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

sharding sphere 4.0.0-RC1版本 按年分表(后续优化)

1. sharding sphere 4.0.0-RC1版本 按年分表(后续优化) 1.1. 概述

关于上一篇中LogShardingAlgorithm的tables,我原先是在第一次调用的时候初始化,这样做虽然能实现功能,但每次调用都会走这个if判断,虽然性能损耗不大,但我觉得这不是业务应该走的逻辑顺序,我的理想是在LogShardingAlgorithm被实例化后去自动初始化tables

现在面对的问题是LogShardingAlgorithm的实例化是在Spring初始化中间执行的,且它本身的创建不是通过Spring的@Component等注解生成,而是通过反射实例化。若在实例化刚开始,也就是构造方法执行的时候执行初始化,那时候applicationContext还没有初始化完毕,拿不到环境参数,连Datasource也还没开始初始化

1.2. 解决方法

经过改造后,代码如下,单独拎出一个初始化方法,在类对象实例化后调用

@Slf4j
public class LogShardingAlgorithm implements PreciseShardingAlgorithm, RangeShardingAlgorithm {

    
    private List tables;

    private final String systemLogHead = "system_log_";

    public void init(){
 tables = DBUtil.getAllSystemLogTable();
    }

    @Override
    public String doSharding(Collection availableTargetNames, PreciseShardingValue shardingValue) {
 String target = shardingValue.getValue().toString();
 String year = target.substring(target.lastIndexOf("_") + 1, target.lastIndexOf("_") + 5);
 if (!tables.contains(systemLogHead + year)) {
     DBUtil.createLogTable(year);
     tables.add(year);
 }
 return shardingValue.getLogicTableName() + "_" + year;
    }

    @Override
    public Collection doSharding(Collection availableTargetNames, RangeShardingValue shardingValue) {
 Collection availables = new ArrayList<>();
 Range valueRange = shardingValue.getValueRange();
 for (String target : tables) {
     Integer shardValue = Integer.parseInt(target.substring(target.lastIndexOf("_") + 1, target.lastIndexOf("_") + 5));
     if (valueRange.hasLowerBound()) {
  String lowerStr = valueRange.lowerEndpoint().toString();
  Integer start = Integer.parseInt(lowerStr.substring(0, 4));
  if (start - shardValue > 0) {
      continue;
  }
     }
     if (valueRange.hasUpperBound()) {
  String upperStr = valueRange.upperEndpoint().toString();
  Integer end = Integer.parseInt(upperStr.substring(0, 4));
  if (end - shardValue < 0) {
      continue;
  }
     }
     availables.add(target);
 }
 return availables;
    }
}

其中init方法通过另一个类实例化完成后调用,难点在于如何拿到该实例化的LogShardingAlgorithm

import cn.hutool.core.util.ReflectUtil;
import com.google.common.base.Optional;
import com.onegene.platform.system.log.LogShardingAlgorithm;
import org.apache.shardingsphere.core.rule.ShardingRule;
import org.apache.shardingsphere.core.rule.TableRule;
import org.apache.shardingsphere.core.strategy.route.ShardingStrategy;
import org.apache.shardingsphere.shardingjdbc.jdbc.core.ShardingContext;
import org.apache.shardingsphere.shardingjdbc.jdbc.core.datasource.ShardingDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.sql.DataSource;

@Component
public class StartupConfig {
    @Autowired
    private DataSource dataSource;

    @PostConstruct
    public void init() {
 this.loadLogInit();
    }

    private void loadLogInit() {
 if (dataSource instanceof ShardingDataSource) {
     ShardingDataSource sds = (ShardingDataSource) dataSource;
     ShardingContext shardingContext = sds.getShardingContext();
     ShardingRule shardingRule = shardingContext.getShardingRule();
     Optional systemLog = shardingRule.findTableRule("system_log");
     TableRule tableRule = systemLog.orNull();
     if (tableRule != null) {
  ShardingStrategy tableShardingStrategy = tableRule.getTableShardingStrategy();
  LogShardingAlgorithm preciseShardingAlgorithm = (LogShardingAlgorithm) ReflectUtil.getFieldValue(tableShardingStrategy, "preciseShardingAlgorithm");
  LogShardingAlgorithm rangeShardingAlgorithm = (LogShardingAlgorithm) ReflectUtil.getFieldValue(tableShardingStrategy, "rangeShardingAlgorithm");
  preciseShardingAlgorithm.init();
  rangeShardingAlgorithm.init();
     }
 }
    }
}
1.3. 总结

通过查看源码可以知道,它最后把LogShardingAlgorithm实例化的对象放入了ShardingDataSource,那我们就要从里面把它取出来,若它正常没提供get方法,那我们就用反射硬把它取出来

通过上述代码可以看出,范围分片和精确分片需要实例化两个类,我想是否可以合到一个类,网上也找了一下,发现有的版本使用ComplexKeysShardingAlgorithm算法是可以同时实现范围和精确分片查询的,但经过我实际测试,现在的4.0.0版本不行,原因在于以下代码,此为复杂分片源码

public final class ComplexShardingStrategy implements ShardingStrategy {
    
    @Getter
    private final Collection shardingColumns;
    
    private final ComplexKeysShardingAlgorithm shardingAlgorithm;
    
    public ComplexShardingStrategy(final ComplexShardingStrategyConfiguration complexShardingStrategyConfig) {
 Preconditions.checkNotNull(complexShardingStrategyConfig.getShardingColumns(), "Sharding columns cannot be null.");
 Preconditions.checkNotNull(complexShardingStrategyConfig.getShardingAlgorithm(), "Sharding algorithm cannot be null.");
 shardingColumns = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
 shardingColumns.addAll(Splitter.on(",").trimResults().splitToList(complexShardingStrategyConfig.getShardingColumns()));
 shardingAlgorithm = complexShardingStrategyConfig.getShardingAlgorithm();
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public Collection doSharding(final Collection availableTargetNames, final Collection shardingValues) {
 Map>> columnShardingValues = new HashMap<>(shardingValues.size(), 1);
 String logicTableName = "";
 for (Routevalue each : shardingValues) {

     // 重点这里他把each的值强行转化成了ListRoutevalue而范围查询对应的为BetweenRoutevalue,所以在源码级别就被卡死了,除非重写策略,否则这个已经不能像以前那样用了
     columnShardingValues.put(each.getColumnName(), ((ListRoutevalue) each).getValues());
     logicTableName = each.getTableName();
 }
 Collection shardingResult = shardingAlgorithm.doSharding(availableTargetNames, new ComplexKeysShardingValue(logicTableName, columnShardingValues));
 Collection result = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
 result.addAll(shardingResult);
 return result;
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/238013.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号