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

系列

  • Sharding-JDBC 核心组件介绍
  • Sharding-JDBC 配置分析
  • Sharding-JDBC 执行整体流程
  • Sharding-JDBC 分库配置解析过程
  • Sharding-JDBC 分表配置解析过程
  • Sharding-JDBC 分库分表配置解析过程


开篇

  • 案例代码参考shardingsphere-example,版本基于4.0.0的tag版本。
  • 这篇文章用来分析分库分表配置的整个解析过程,根据shardingRuleConfig来生成shardingRule对象。


分库分表策略

支持策略

public enum ShardingType {
    // 分库
    SHARDING_DATABASES,
    // 分表
    SHARDING_TABLES,
    // 分库分表
    SHARDING_DATABASES_AND_TABLES,
    // 主从
    MASTER_SLAVE,
    // 分片下的主从
    SHARDING_MASTER_SLAVE,
    // 加密
    ENCRYPT
}
  • 支持分库、分表、分库分表、主从、分片下的主从、加密等共6种场景。

精确值的分库分表策略

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());
        }
    }
}
  • 按照精确值进行分库分表策略配置对象。
  • 支持分库、分表、分库分表、主从、分片的主从等5类场景。

范围值的分库分表策略

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());
        }
    }
}
  • 按照范围值进行分库分表策略配置对象。
  • 支持分库、分表、分库分表、主从、分片的主从等5类场景。


精确值分表配置

配置的源码实现

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 createDataSourceMap() {
        Map 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 {
    
    @Override
    public String doSharding(final Collection tableNames, final PreciseShardingValue shardingValue) {
        for (String each : tableNames) {
            if (each.endsWith(shardingValue.getValue() % 2 + "")) {
                return each;
            }
        }
        throw new UnsupportedOperationException();
    }
}
  • 配置两个DataSource的demo_ds_0和demo_ds_1用于分库。
  • 分库的策略为demo_ds_${user_id % 2},按照uid进行分库选择。
  • 分表的策略为shardingValue.getValue() % 2 + "",按照order_id进行分表选择。


配置的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"
        }]
}
  • 包含t_order和t_order_item两个tableRuleConfig。
  • 逻辑表t_order的实际数据节点为"demo_ds_${0..1}.t_order_${[0, 1]}"。
  • 逻辑表t_order_item的实际节点为"demo_ds.t_order_item_${[0, 1]}"。


配置规则的解析

public final class ShardingDataSourceFactory {

    public static DataSource createDataSource(
            final Map dataSourceMap, final ShardingRuleConfiguration shardingRuleConfig, final Properties props) throws SQLException {
        return new ShardingDataSource(dataSourceMap, new ShardingRule(shardingRuleConfig, dataSourceMap.keySet()), props);
    }
}
  • 基于shardingRuleConfig和dataSourceMap生成ShardingRule对象。


public class ShardingRule implements BaseRule {

    private final ShardingRuleConfiguration ruleConfiguration;
    private final ShardingDataSourceNames shardingDataSourceNames;
    private final Collection tableRules;
    private final Collection bindingTableRules;
    private final Collection broadcastTables;
    private final ShardingStrategy defaultDatabaseShardingStrategy;
    private final ShardingStrategy defaultTableShardingStrategy;
    private final ShardingKeyGenerator defaultShardingKeyGenerator;
    private final Collection masterSlaveRules;
    private final EncryptRule encryptRule;

    public ShardingRule(final ShardingRuleConfiguration shardingRuleConfig, final Collection 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());
    }
}
  • 整体逻辑的注释如上所示,核心关注tableRules和defaultTableShardingStrategy和defaultDatabaseShardingStrategy。
  • ShardingDataSourceNames记录分库的数据源。
  • defaultTableShardingStrategy表示table的分表策略
  • defaultDatabaseShardingStrategy表示database的分库策略


public final class ShardingDataSourceNames {
    
    private final ShardingRuleConfiguration shardingRuleConfig;
    
    @Getter
    private final Collection dataSourceNames;
    
    public ShardingDataSourceNames(final ShardingRuleConfiguration shardingRuleConfig, final Collection rawDataSourceNames) {
        Preconditions.checkArgument(null != shardingRuleConfig, "can not construct ShardingDataSourceNames with null ShardingRuleConfig");
        this.shardingRuleConfig = shardingRuleConfig;
        dataSourceNames = getAllDataSourceNames(rawDataSourceNames);
    }
    
    private Collection getAllDataSourceNames(final Collection dataSourceNames) {
        Collection result = new LinkedHashSet<>(dataSourceNames);
        for (MasterSlaveRuleConfiguration each : shardingRuleConfig.getMasterSlaveRuleConfigs()) {
            result.remove(each.getMasterDataSourceName());
            result.removeAll(each.getSlaveDataSourceNames());
            result.add(each.getName());
        }
        return result;
    }
}
  • ShardingDataSourceNames的生成规则为包含传入的dataSourceNames,然后排除MasterSlaveRuleConfiguration的主从的DataSourceNames并添加对应的name。
  • 在分库分表的场景下dataSourceNames的配置信息为:{"dataSourceNames":["demo_ds_1","demo_ds_0"],"randomDataSourceName":"demo_ds_1"}


public class ShardingRule implements BaseRule {

    private Collection createTableRules(final ShardingRuleConfiguration shardingRuleConfig) {
        // 1、getTableRuleConfigs的结果可以参考分库的json格式配置内容
        Collection tableRuleConfigurations = shardingRuleConfig.getTableRuleConfigs();
        // 每个表对应一个TableRule对象
        Collection 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 actualDataNodes;
    private final Set actualTables;
    private final Map dataNodeIndexMap;
    private final ShardingStrategy databaseShardingStrategy;
    private final ShardingStrategy tableShardingStrategy;
    private final String generateKeyColumn;
    private final ShardingKeyGenerator shardingKeyGenerator;
    private final Collection actualDatasourceNames = new LinkedHashSet<>();
    private final Map> 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 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 generateDataNodes(final List actualDataNodes, final Collection dataSourceNames) {
        List 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 segments = Splitter.on(DELIMITER).splitToList(dataNode);
        dataSourceName = segments.get(0);
        tableName = segments.get(1);
    }
}
  • TableRule记录的是每个表的分库后的结果。
    TableRule的核心变量包括logicTable逻辑、actualDataNodes实际数据存储节点。
  • databaseShardingStrategy为分库策略,tableShardingStrategy分表策略。
  • 分库分表场景下t_order的actualDataNodes包含["demo_ds_0.t_order_0",
    "demo_ds_0.t_order_1","demo_ds_1.t_order_0","demo_ds_1.t_order_1"]
  • 分库分表场景下t_order_item的actualDataNodes包含["demo_ds_0.t_order_item_0",
    "demo_ds_0.t_order_item_1","demo_ds_1.t_order_item_0","demo_ds_1.t_order_item_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();
    }
}
  • 分库分表场景下分表策略为StandardShardingStrategy。
  • 分库分表场景下分库策略为InlineShardingStrategyConfiguration。


分库过程

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 doSharding(final Collection availableTargetNames, final Collection 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 shardingResult = doSharding((ListRouteValue) shardingValue);
        Collection result = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
        for (String each : shardingResult) {
            if (availableTargetNames.contains(each)) {
                result.add(each);
            }
        }

        return result;
    }
    
    private Collection doSharding(final ListRouteValue shardingValue) {
        Collection result = new LinkedList<>();
        // 将shardingValue转为PreciseShardingValue
        for (PreciseShardingValue each : transferToPreciseShardingValues(shardingValue)) {
            // 通过执行execute方法来将分片值通过分片表达式来进行执行并返回结果
            result.add(execute(each));
        }
        return result;
    }
    
    @SuppressWarnings("unchecked")
    private List transferToPreciseShardingValues(final ListRouteValue shardingValue) {
        // 将分片的值转为PreciseShardingValue对象
        List 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();
    }
}
  • ShardingStrategyFactory为分片策略工程,分库场景为InlineShardingStrategy对象。
  • InlineShardingStrategy包含分片的列shardingColumn和分片的表达式algorithmExpression,同时根据algorithmExpression来生成执行闭包closure。
  • doSharding过程根据ListRouteValue的值通过分片表达式闭包计算分片结果。
  • 在["demo_ds_0","demo_ds_1"]两个库当中,根据分库规则[{"columnName":"user_id",
    "tableName":"t_order","values":[1]}]选择demo_ds_1。


public final class PreciseShardingValue> 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> implements RouteValue {
    // 列名
    private final String columnName;
    // 表名
    private final String tableName;
    // 对应的值
    private final Collection values;
    
    @Override
    public String toString() {
        return tableName + "." + columnName + (1 == values.size() ? " = " + new ArrayList<>(values).get(0) : " in (" + Joiner.on(",").join(values) + ")");
    }
}
  • ListRouteValue的内容为{"columnName":"user_id","tableName":"t_order","values":[1]}。


分表过程

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 doSharding(final Collection availableTargetNames, final Collection shardingValues) {
        // t_order维度下availableTargetNames为t_order_0和t_order_1
        // t_order维度下shardingValues为t_order.order_id = 479354537787240448
        RouteValue shardingValue = shardingValues.iterator().next();
        Collection shardingResult = shardingValue instanceof ListRouteValue
                ? doSharding(availableTargetNames, (ListRouteValue) shardingValue) : doSharding(availableTargetNames, (RangeRouteValue) shardingValue);
        Collection result = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
        result.addAll(shardingResult);
        return result;
    }

    @SuppressWarnings("unchecked")
    private Collection doSharding(final Collection availableTargetNames, final ListRouteValue shardingValue) {
        Collection 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 getShardingColumns() {
        Collection result = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
        result.add(shardingColumn);
        return result;
    }
}
  • StandardShardingStrategy需要自定义精确分表的算法,如例子中的PreciseModuloShardingTableAlgorithm。
  • 自定义分片的逻辑按照具体的分片的列值和逻辑表的个数取模确定应该落到具体那个表当中。


// 自定义的精确分表算法实现
public final class PreciseModuloShardingTableAlgorithm implements PreciseShardingAlgorithm {
    
    @Override
    public String doSharding(final Collection tableNames, final PreciseShardingValue shardingValue) {
        for (String each : tableNames) {
            // 数据库的实际物理节点名和取模后的值比较相等直接返回
            if (each.endsWith(shardingValue.getValue() % 2 + "")) {
                return each;
            }
        }
        throw new UnsupportedOperationException();
    }
}
  • t_order包含["t_order_0","t_order_1"],shardingValue的值为481399646347309056。
  • 表的取模后返回t_order_0。


总结

  • 分库分表的逻辑是结合了分库和分表的逻辑。
  • 先通过分库的逻辑选择数据库,然后根据分表的逻辑选择数据表。

你可能感兴趣的:(Sharding-JDBC 分库分表配置解析过程)