ShardingSphere

Sharding-JDBC 分库分表配置解析过程

2020-06-21  本文已影响0人  晴天哥_王志

系列

开篇

分库分表策略

支持策略

public enum ShardingType {
    // 分库
    SHARDING_DATABASES,
    // 分表
    SHARDING_TABLES,
    // 分库分表
    SHARDING_DATABASES_AND_TABLES,
    // 主从
    MASTER_SLAVE,
    // 分片下的主从
    SHARDING_MASTER_SLAVE,
    // 加密
    ENCRYPT
}

精确值的分库分表策略

public class DataSourceFactory {
    // 精确值的分库分表策略
    public static DataSource newInstance(final ShardingType shardingType) throws SQLException {
        switch (shardingType) {
            // 分库
            case SHARDING_DATABASES:
                return new ShardingDatabasesConfigurationPrecise().getDataSource();
            // 分表
            case SHARDING_TABLES:
                return new ShardingTablesConfigurationPrecise().getDataSource();
            // 分库分表
            case SHARDING_DATABASES_AND_TABLES:
                return new ShardingDatabasesAndTablesConfigurationPrecise().getDataSource();
            // 主从
            case MASTER_SLAVE:
                return new MasterSlaveConfiguration().getDataSource();
            // 分片场景下的主从
            case SHARDING_MASTER_SLAVE:
                return new ShardingMasterSlaveConfigurationPrecise().getDataSource();
            default:
                throw new UnsupportedOperationException(shardingType.name());
        }
    }
}

范围值的分库分表策略

public class RangeDataSourceFactory {
    // 范围值的分库分表策略
    public static DataSource newInstance(final ShardingType shardingType) throws SQLException {
        switch (shardingType) {
            // 分库
            case SHARDING_DATABASES:
                return new ShardingDatabasesConfigurationRange().getDataSource();
            // 分表
            case SHARDING_TABLES:
                return new ShardingTablesConfigurationRange().getDataSource();
            // 分库分表
            case SHARDING_DATABASES_AND_TABLES:
                return new ShardingDatabasesAndTablesConfigurationRange().getDataSource();
            // 主从
            case MASTER_SLAVE:
                return new MasterSlaveConfiguration().getDataSource();
            // 分片下的主从关系
            case SHARDING_MASTER_SLAVE:
                return new ShardingMasterSlaveConfigurationRange().getDataSource();
            default:
                throw new UnsupportedOperationException(shardingType.name());
        }
    }
}

精确值分表配置

配置的源码实现

public final class ShardingDatabasesAndTablesConfigurationPrecise implements ExampleConfiguration {
    
    @Override
    public DataSource getDataSource() throws SQLException {
        ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
        shardingRuleConfig.getTableRuleConfigs().add(getOrderTableRuleConfiguration());
        shardingRuleConfig.getTableRuleConfigs().add(getOrderItemTableRuleConfiguration());
        shardingRuleConfig.getBindingTableGroups().add("t_order, t_order_item");
        shardingRuleConfig.getBroadcastTables().add("t_address");
        shardingRuleConfig.setDefaultDatabaseShardingStrategyConfig(new InlineShardingStrategyConfiguration("user_id", "demo_ds_${user_id % 2}"));
        shardingRuleConfig.setDefaultTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new PreciseModuloShardingTableAlgorithm()));
        return ShardingDataSourceFactory.createDataSource(createDataSourceMap(), shardingRuleConfig, new Properties());
    }
    
    private static TableRuleConfiguration getOrderTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration("t_order", "demo_ds_${0..1}.t_order_${[0, 1]}");
        result.setKeyGeneratorConfig(new KeyGeneratorConfiguration("SNOWFLAKE", "order_id", getProperties()));
        return result;
    }
    
    private static TableRuleConfiguration getOrderItemTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration("t_order_item", "demo_ds_${0..1}.t_order_item_${[0, 1]}");
        result.setKeyGeneratorConfig(new KeyGeneratorConfiguration("SNOWFLAKE", "order_item_id", getProperties()));
        return result;
    }
    
    private static Map<String, DataSource> createDataSourceMap() {
        Map<String, DataSource> result = new HashMap<>();
        result.put("demo_ds_0", DataSourceUtil.createDataSource("demo_ds_0"));
        result.put("demo_ds_1", DataSourceUtil.createDataSource("demo_ds_1"));
        return result;
    }
    
    private static Properties getProperties() {
        Properties result = new Properties();
        result.setProperty("worker.id", "123");
        return result;
    }
}


public final class PreciseModuloShardingTableAlgorithm implements PreciseShardingAlgorithm<Long> {
    
    @Override
    public String doSharding(final Collection<String> tableNames, final PreciseShardingValue<Long> shardingValue) {
        for (String each : tableNames) {
            if (each.endsWith(shardingValue.getValue() % 2 + "")) {
                return each;
            }
        }
        throw new UnsupportedOperationException();
    }
}

配置的json格式

{
    "bindingTableGroups":["t_order, t_order_item"],
    "broadcastTables":["t_address"],
    "defaultDatabaseShardingStrategyConfig":{
        "algorithmExpression":"demo_ds_${user_id % 2}",
        "shardingColumn":"user_id"
    },
    "defaultTableShardingStrategyConfig":{
        "preciseShardingAlgorithm":{
        },
        "shardingColumn":"order_id"
    },
    "masterSlaveRuleConfigs":[],
    "tableRuleConfigs":[
        {
            "actualDataNodes":"demo_ds_${0..1}.t_order_${[0, 1]}",
            "keyGeneratorConfig":{
                "column":"order_id",
                "properties":{
                    "worker.id":"123"
                },
                "type":"SNOWFLAKE"
            },
            "logicTable":"t_order"
        },
        {
            "actualDataNodes":"demo_ds_${0..1}.t_order_item_${[0, 1]}",
            "keyGeneratorConfig":{
                "column":"order_item_id",
                "properties":{
                    "worker.id":"123"
                },
                "type":"SNOWFLAKE"
            },
            "logicTable":"t_order_item"
        }]
}

配置规则的解析

public final class ShardingDataSourceFactory {

    public static DataSource createDataSource(
            final Map<String, DataSource> dataSourceMap, final ShardingRuleConfiguration shardingRuleConfig, final Properties props) throws SQLException {
        return new ShardingDataSource(dataSourceMap, new ShardingRule(shardingRuleConfig, dataSourceMap.keySet()), props);
    }
}
public class ShardingRule implements BaseRule {

    private final ShardingRuleConfiguration ruleConfiguration;
    private final ShardingDataSourceNames shardingDataSourceNames;
    private final Collection<TableRule> tableRules;
    private final Collection<BindingTableRule> bindingTableRules;
    private final Collection<String> broadcastTables;
    private final ShardingStrategy defaultDatabaseShardingStrategy;
    private final ShardingStrategy defaultTableShardingStrategy;
    private final ShardingKeyGenerator defaultShardingKeyGenerator;
    private final Collection<MasterSlaveRule> masterSlaveRules;
    private final EncryptRule encryptRule;

    public ShardingRule(final ShardingRuleConfiguration shardingRuleConfig, final Collection<String> dataSourceNames) {
        Preconditions.checkArgument(null != shardingRuleConfig, "ShardingRuleConfig cannot be null.");
        Preconditions.checkArgument(null != dataSourceNames && !dataSourceNames.isEmpty(), "Data sources cannot be empty.");
        // 1、分片规则
        this.ruleConfiguration = shardingRuleConfig;
        // 2、解析生成数据源名字
        shardingDataSourceNames = new ShardingDataSourceNames(shardingRuleConfig, dataSourceNames);
        // 3、生成TableRule
        tableRules = createTableRules(shardingRuleConfig);
        // 4、生成broadcastTables
        broadcastTables = shardingRuleConfig.getBroadcastTables();
        // 5、生成BindingTableRule
        bindingTableRules = createBindingTableRules(shardingRuleConfig.getBindingTableGroups());
        // 6、生成分库策略defaultDatabaseShardingStrategy
        defaultDatabaseShardingStrategy = createDefaultShardingStrategy(shardingRuleConfig.getDefaultDatabaseShardingStrategyConfig());
        // 7、生成分表策略defaultTableShardingStrategy
        defaultTableShardingStrategy = createDefaultShardingStrategy(shardingRuleConfig.getDefaultTableShardingStrategyConfig());
        // 8、生成分片key的生成器defaultShardingKeyGenerator
        defaultShardingKeyGenerator = createDefaultKeyGenerator(shardingRuleConfig.getDefaultKeyGeneratorConfig());
        // 9、生成MasterSlaveRule
        masterSlaveRules = createMasterSlaveRules(shardingRuleConfig.getMasterSlaveRuleConfigs());
        // 10、生成EncryptRule
        encryptRule = createEncryptRule(shardingRuleConfig.getEncryptRuleConfig());
    }
}
public final class ShardingDataSourceNames {
    
    private final ShardingRuleConfiguration shardingRuleConfig;
    
    @Getter
    private final Collection<String> dataSourceNames;
    
    public ShardingDataSourceNames(final ShardingRuleConfiguration shardingRuleConfig, final Collection<String> rawDataSourceNames) {
        Preconditions.checkArgument(null != shardingRuleConfig, "can not construct ShardingDataSourceNames with null ShardingRuleConfig");
        this.shardingRuleConfig = shardingRuleConfig;
        dataSourceNames = getAllDataSourceNames(rawDataSourceNames);
    }
    
    private Collection<String> getAllDataSourceNames(final Collection<String> dataSourceNames) {
        Collection<String> result = new LinkedHashSet<>(dataSourceNames);
        for (MasterSlaveRuleConfiguration each : shardingRuleConfig.getMasterSlaveRuleConfigs()) {
            result.remove(each.getMasterDataSourceName());
            result.removeAll(each.getSlaveDataSourceNames());
            result.add(each.getName());
        }
        return result;
    }
}
public class ShardingRule implements BaseRule {

    private Collection<TableRule> createTableRules(final ShardingRuleConfiguration shardingRuleConfig) {
        // 1、getTableRuleConfigs的结果可以参考分库的json格式配置内容
        Collection<TableRuleConfiguration> tableRuleConfigurations = shardingRuleConfig.getTableRuleConfigs();
        // 每个表对应一个TableRule对象
        Collection<TableRule> result = new ArrayList<>(tableRuleConfigurations.size());
        // 2、遍历tableRuleConfigurations生成TableRule
        for (TableRuleConfiguration each : tableRuleConfigurations) {
            // 3、每个table对应一个TableRuleConfiguration,每个TableRuleConfiguration生成TableRule对象
            result.add(new TableRule(each, shardingDataSourceNames, getDefaultGenerateKeyColumn(shardingRuleConfig)));
        }
        return result;
    }

    private String getDefaultGenerateKeyColumn(final ShardingRuleConfiguration shardingRuleConfig) {
        return null == shardingRuleConfig.getDefaultKeyGeneratorConfig() ? null : shardingRuleConfig.getDefaultKeyGeneratorConfig().getColumn();
    }
}


public final class TableRule {
    
    private final String logicTable;
    private final List<DataNode> actualDataNodes;
    private final Set<String> actualTables;
    private final Map<DataNode, Integer> dataNodeIndexMap;
    private final ShardingStrategy databaseShardingStrategy;
    private final ShardingStrategy tableShardingStrategy;
    private final String generateKeyColumn;
    private final ShardingKeyGenerator shardingKeyGenerator;
    private final Collection<String> actualDatasourceNames = new LinkedHashSet<>();
    private final Map<String, Collection<String>> datasourceToTablesMap = new HashMap<>();

    public TableRule(final TableRuleConfiguration tableRuleConfig, final ShardingDataSourceNames shardingDataSourceNames, final String defaultGenerateKeyColumn) {
        // 生成逻辑表名logicTable
        logicTable = tableRuleConfig.getLogicTable().toLowerCase();
        // 解析actualNodes生成dataNodes,分表的场景下这个值为demo_ds.t_order_0和demo_ds.t_order_1
        List<String> dataNodes = new InlineExpressionParser(tableRuleConfig.getActualDataNodes()).splitAndEvaluate();
        dataNodeIndexMap = new HashMap<>(dataNodes.size(), 1);
        // 生成实际的DataNode节点,不同场景使用不同的策略
        actualDataNodes = isEmptyDataNodes(dataNodes)
            ? generateDataNodes(tableRuleConfig.getLogicTable(), shardingDataSourceNames.getDataSourceNames()) : generateDataNodes(dataNodes, shardingDataSourceNames.getDataSourceNames());
        // 获取实际的表名,获取actualDataNode种DataNode的表名
        actualTables = getActualTables();
        // 分库策略
        databaseShardingStrategy = null == tableRuleConfig.getDatabaseShardingStrategyConfig() ? null : ShardingStrategyFactory.newInstance(tableRuleConfig.getDatabaseShardingStrategyConfig());
        // 分表策略
        tableShardingStrategy = null == tableRuleConfig.getTableShardingStrategyConfig() ? null : ShardingStrategyFactory.newInstance(tableRuleConfig.getTableShardingStrategyConfig());
        // 生成key的列名
        generateKeyColumn = getGenerateKeyColumn(tableRuleConfig.getKeyGeneratorConfig(), defaultGenerateKeyColumn);
        // key的生成器
        shardingKeyGenerator = containsKeyGeneratorConfiguration(tableRuleConfig)
                ? new ShardingKeyGeneratorServiceLoader().newService(tableRuleConfig.getKeyGeneratorConfig().getType(), tableRuleConfig.getKeyGeneratorConfig().getProperties()) : null;
        checkRule(dataNodes);
    }
    
    private List<DataNode> generateDataNodes(final List<String> actualDataNodes, final Collection<String> dataSourceNames) {
        List<DataNode> result = new LinkedList<>();
        int index = 0;
        for (String each : actualDataNodes) {
            DataNode dataNode = new DataNode(each);
            if (!dataSourceNames.contains(dataNode.getDataSourceName())) {
                throw new ShardingException("Cannot find data source in sharding rule, invalid actual data node is: '%s'", each);
            }
            result.add(dataNode);
            dataNodeIndexMap.put(dataNode, index);
            actualDatasourceNames.add(dataNode.getDataSourceName());
            addActualTable(dataNode.getDataSourceName(), dataNode.getTableName());
            index++;
        }
        return result;
    }
}

public final class DataNode {
    private static final String DELIMITER = ".";
    // 所属的数据源
    private final String dataSourceName;
    // 逻辑表名
    private final String tableName;

    public DataNode(final String dataNode) {
        if (!isValidDataNode(dataNode)) {
            throw new ShardingConfigurationException("Invalid format for actual data nodes: '%s'", dataNode);
        }
        // 通过符号"."进行分割,获取dataSourceName和tableName
        List<String> segments = Splitter.on(DELIMITER).splitToList(dataNode);
        dataSourceName = segments.get(0);
        tableName = segments.get(1);
    }
}
public final class ShardingStrategyFactory {
    
    public static ShardingStrategy newInstance(final ShardingStrategyConfiguration shardingStrategyConfig) {
        // 1、分库分表场景下分表的策略为StandardShardingStrategyConfiguration
        if (shardingStrategyConfig instanceof StandardShardingStrategyConfiguration) {
            return new StandardShardingStrategy((StandardShardingStrategyConfiguration) shardingStrategyConfig);
        }
        // 2、分库分表场景下分库的策略为InlineShardingStrategyConfiguration
        if (shardingStrategyConfig instanceof InlineShardingStrategyConfiguration) {
            return new InlineShardingStrategy((InlineShardingStrategyConfiguration) shardingStrategyConfig);
        }
        if (shardingStrategyConfig instanceof ComplexShardingStrategyConfiguration) {
            return new ComplexShardingStrategy((ComplexShardingStrategyConfiguration) shardingStrategyConfig);
        }
        if (shardingStrategyConfig instanceof HintShardingStrategyConfiguration) {
            return new HintShardingStrategy((HintShardingStrategyConfiguration) shardingStrategyConfig);
        }
        return new NoneShardingStrategy();
    }
}

分库过程

public final class InlineShardingStrategy implements ShardingStrategy {
    
    private final String shardingColumn;
    private final Closure<?> closure;
    
    public InlineShardingStrategy(final InlineShardingStrategyConfiguration inlineShardingStrategyConfig) {
        Preconditions.checkNotNull(inlineShardingStrategyConfig.getShardingColumn(), "Sharding column cannot be null.");
        Preconditions.checkNotNull(inlineShardingStrategyConfig.getAlgorithmExpression(), "Sharding algorithm expression cannot be null.");
        // 分片的列名
        shardingColumn = inlineShardingStrategyConfig.getShardingColumn();
        // 分片的表达式
        String algorithmExpression = InlineExpressionParser.handlePlaceHolder(inlineShardingStrategyConfig.getAlgorithmExpression().trim());
        // 根据分片的表达式生成执行闭包
        closure = new InlineExpressionParser(algorithmExpression).evaluateClosure();
    }

    @Override
    public Collection<String> doSharding(final Collection<String> availableTargetNames, final Collection<RouteValue> shardingValues) {
        // availableTargetNames包含["demo_ds_0","demo_ds_1"]
        // shardingValue为[{"columnName":"user_id","tableName":"t_order","values":[1]}]
        RouteValue shardingValue = shardingValues.iterator().next();
        Preconditions.checkState(shardingValue instanceof ListRouteValue, "Inline strategy cannot support range sharding.");
        // 根据查询值ListRouteValue来执行分片操作,在这个场景返回["demo_ds_1"]
        Collection<String> shardingResult = doSharding((ListRouteValue) shardingValue);
        Collection<String> result = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
        for (String each : shardingResult) {
            if (availableTargetNames.contains(each)) {
                result.add(each);
            }
        }

        return result;
    }
    
    private Collection<String> doSharding(final ListRouteValue shardingValue) {
        Collection<String> result = new LinkedList<>();
        // 将shardingValue转为PreciseShardingValue
        for (PreciseShardingValue<?> each : transferToPreciseShardingValues(shardingValue)) {
            // 通过执行execute方法来将分片值通过分片表达式来进行执行并返回结果
            result.add(execute(each));
        }
        return result;
    }
    
    @SuppressWarnings("unchecked")
    private List<PreciseShardingValue> transferToPreciseShardingValues(final ListRouteValue<?> shardingValue) {
        // 将分片的值转为PreciseShardingValue对象
        List<PreciseShardingValue> result = new ArrayList<>(shardingValue.getValues().size());
        for (Comparable<?> each : shardingValue.getValues()) {
            result.add(new PreciseShardingValue(shardingValue.getTableName(), shardingValue.getColumnName(), each));
        }
        return result;
    }
    
    private String execute(final PreciseShardingValue shardingValue) {
        // 将分片值通过分片表达式的闭包执行并返回结果
        Closure<?> result = closure.rehydrate(new Expando(), null, null);
        result.setResolveStrategy(Closure.DELEGATE_ONLY);
        result.setProperty(shardingColumn, shardingValue.getValue());

        // 执行call返回结果
        return result.call().toString();
    }
}
public final class PreciseShardingValue<T extends Comparable<?>> implements ShardingValue {
    // 逻辑表名
    private final String logicTableName;
    // 列名
    private final String columnName;
    // 对应的列值
    private final T value;

    @ConstructorProperties({"logicTableName", "columnName", "value"})
    public PreciseShardingValue(String logicTableName, String columnName, T value) {
        this.logicTableName = logicTableName;
        this.columnName = columnName;
        this.value = value;
    }
}

public final class ListRouteValue<T extends Comparable<?>> implements RouteValue {
    // 列名
    private final String columnName;
    // 表名
    private final String tableName;
    // 对应的值
    private final Collection<T> values;
    
    @Override
    public String toString() {
        return tableName + "." + columnName + (1 == values.size() ? " = " + new ArrayList<>(values).get(0) : " in (" + Joiner.on(",").join(values) + ")");
    }
}

分表过程

public final class StandardShardingStrategy implements ShardingStrategy {
    // 分表的列表
    private final String shardingColumn;
    // 按值精确分表的算法
    private final PreciseShardingAlgorithm preciseShardingAlgorithm;
    // 按指范围分表的算法
    private final RangeShardingAlgorithm rangeShardingAlgorithm;
    
    public StandardShardingStrategy(final StandardShardingStrategyConfiguration standardShardingStrategyConfig) {
        Preconditions.checkNotNull(standardShardingStrategyConfig.getShardingColumn(), "Sharding column cannot be null.");
        Preconditions.checkNotNull(standardShardingStrategyConfig.getPreciseShardingAlgorithm(), "precise sharding algorithm cannot be null.");
        // 分表的列名 order_id
        shardingColumn = standardShardingStrategyConfig.getShardingColumn();
        preciseShardingAlgorithm = standardShardingStrategyConfig.getPreciseShardingAlgorithm();
        rangeShardingAlgorithm = standardShardingStrategyConfig.getRangeShardingAlgorithm();
    }
    
    @Override
    public Collection<String> doSharding(final Collection<String> availableTargetNames, final Collection<RouteValue> shardingValues) {
        // t_order维度下availableTargetNames为t_order_0和t_order_1
        // t_order维度下shardingValues为t_order.order_id = 479354537787240448
        RouteValue shardingValue = shardingValues.iterator().next();
        Collection<String> shardingResult = shardingValue instanceof ListRouteValue
                ? doSharding(availableTargetNames, (ListRouteValue) shardingValue) : doSharding(availableTargetNames, (RangeRouteValue) shardingValue);
        Collection<String> result = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
        result.addAll(shardingResult);
        return result;
    }

    @SuppressWarnings("unchecked")
    private Collection<String> doSharding(final Collection<String> availableTargetNames, final ListRouteValue<?> shardingValue) {
        Collection<String> result = new LinkedList<>();
        // t_order维度下availableTargetNames为t_order_0和t_order_1
        // t_order维度下shardingValue为t_order.order_id = 479354537787240448
        for (Comparable<?> each : shardingValue.getValues()) {
            // 通过preciseShardingAlgorithm来执行分片操作
            String target = preciseShardingAlgorithm.doSharding(availableTargetNames, new PreciseShardingValue(shardingValue.getTableName(), shardingValue.getColumnName(), each));
            if (null != target) {
                result.add(target);
            }
        }
        return result;
    }
    
    @Override
    public Collection<String> getShardingColumns() {
        Collection<String> result = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
        result.add(shardingColumn);
        return result;
    }
}
// 自定义的精确分表算法实现
public final class PreciseModuloShardingTableAlgorithm implements PreciseShardingAlgorithm<Long> {
    
    @Override
    public String doSharding(final Collection<String> tableNames, final PreciseShardingValue<Long> shardingValue) {
        for (String each : tableNames) {
            // 数据库的实际物理节点名和取模后的值比较相等直接返回
            if (each.endsWith(shardingValue.getValue() % 2 + "")) {
                return each;
            }
        }
        throw new UnsupportedOperationException();
    }
}

总结

上一篇下一篇

猜你喜欢

热点阅读