sharding sphere 4.1.1 - “路由装饰器RouteDecorator-分片” 之 “分片路由-引擎”

.

org.apache.shardingsphere.sharding.route.engine.type.standard.ShardingStandardRoutingEngine

public final class ShardingStandardRoutingEngine implements ShardingRouteEngine {
    private final String logicTableName;

    private final SQLStatementContext sqlStatementContext;

    /**
     * <pre>
     *     // 插入有多少行,有多少条ShardingCondition
     *     List = List<ShardingCondition> : [
     *          ShardingCondition { // 插入某一行数据,提取出来的sharding条件
     *              routeValues : [ // 根据多个列sharding,会有多个值
     *                  ListRouteValue {columnName : "id", tableName : "tb_users", values : ["1"]}
     *                  ListRouteValue {columnName : "city_id", tableName : "tb_users", values : ["2"]}
     *                  ListRouteValue {columnName : "gen_seq_no", tableName : "tb_users", values : ["45678909876545676789"]}  // 自动生成,即:用户编写的sql不包含gen_seq_no字段
     *              ]
     *          }
     *     ]
     * </pre>
     */
    private final ShardingConditions shardingConditions;

    private final ConfigurationProperties properties;

    private final Collection<Collection<DataNode>> originalDataNodes = new LinkedList<>();

    @Override
    public RouteResult route(final ShardingRule shardingRule) {
        if (isDMLForModify(sqlStatementContext) && 1 != ((TableAvailable) sqlStatementContext).getAllTables().size()) {
            throw new ShardingSphereException("Cannot support Multiple-Table for '%s'.", sqlStatementContext.getSqlStatement());
        }
        return generateRouteResult(
                // 数据节点
                getDataNodes(shardingRule, shardingRule.getTableRule(logicTableName))
        );
    }

    private boolean isDMLForModify(final SQLStatementContext sqlStatementContext) {
        return sqlStatementContext instanceof InsertStatementContext || sqlStatementContext instanceof UpdateStatementContext || sqlStatementContext instanceof DeleteStatementContext;
    }

    private RouteResult generateRouteResult(final Collection<DataNode> routedDataNodes) {
        RouteResult result = new RouteResult();
        result.getOriginalDataNodes().addAll(originalDataNodes);
        /**
         * routedDataNodes = [
         *      DataNode : { dataSourceName : "dataSource00", tableName : "tb_users_00"}
         *      DataNode : { dataSourceName : "dataSource00", tableName : "tb_users_01"}
         *      DataNode : { dataSourceName : "dataSource01", tableName : "tb_users_00"}
         *      DataNode : { dataSourceName : "dataSource01", tableName : "tb_users_01"}
         * ]
         */
        for (DataNode each : routedDataNodes) { // 要操作的数据节点列表
            result.getRouteUnits().add(
                    new RouteUnit(new RouteMapper(each.getDataSourceName(), each.getDataSourceName()), Collections.singletonList(new RouteMapper(logicTableName, each.getTableName()))));
        }
        /**
         * <pre>
         *     RouteResult : {
         *         routeUnits : [
         *              RouteUnit : {
         *                  dataSourceMapper : RouteMapper {logicName : "dataSource00", actualName : "dataSource00"},
         *                  tableMappers : [
         *                      RouteMapper : {logicName : "tb_users", actualName : "tb_users_00"}
         *                  ]
         *              },
         *              RouteUnit : {
         *                  dataSourceMapper : RouteMapper {logicName : "dataSource00", actualName : "dataSource00"},
         *                  tableMappers : [
         *                      RouteMapper : {logicName : "tb_users", actualName : "tb_users_01"}
         *                  ]
         *              },
         *              RouteUnit : {
         *                  dataSourceMapper : RouteMapper {logicName : "dataSource01", actualName : "dataSource00"},
         *                  tableMappers : [
         *                      RouteMapper : {logicName : "tb_users", actualName : "tb_users_00"}
         *                  ]
         *              },
         *              RouteUnit : {
         *                  dataSourceMapper : RouteMapper {logicName : "dataSource01", actualName : "dataSource00"},
         *                  tableMappers : [
         *                      RouteMapper : {logicName : "tb_users", actualName : "tb_users_01"}
         *                  ]
         *              }
         *         ]
         *
         *     }
         * </pre>
         */
        return result;
    }

    private Collection<DataNode> getDataNodes(final ShardingRule shardingRule, final TableRule tableRule) {
        // 根据hint分片
        if (isRoutingByHint(shardingRule, tableRule)) {
            return routeByHint(shardingRule, tableRule);
        }

        // 根据condition分片
        if (isRoutingByShardingConditions(shardingRule, tableRule)) {
            return routeByShardingConditions(shardingRule, tableRule); // !!!
        }

        // 混合条件分片
        return routeByMixedConditions(shardingRule, tableRule);
    }

    private boolean isRoutingByHint(final ShardingRule shardingRule, final TableRule tableRule) {
        return shardingRule.getDatabaseShardingStrategy(tableRule) instanceof HintShardingStrategy && shardingRule.getTableShardingStrategy(tableRule) instanceof HintShardingStrategy;
    }

    private Collection<DataNode> routeByHint(final ShardingRule shardingRule, final TableRule tableRule) {
        return route0(shardingRule, tableRule, getDatabaseShardingValuesFromHint(), getTableShardingValuesFromHint());
    }

    private boolean isRoutingByShardingConditions(final ShardingRule shardingRule, final TableRule tableRule) {
        return !(shardingRule.getDatabaseShardingStrategy(tableRule) instanceof HintShardingStrategy || shardingRule.getTableShardingStrategy(tableRule) instanceof HintShardingStrategy);
    }

    private Collection<DataNode> routeByShardingConditions(final ShardingRule shardingRule, final TableRule tableRule) {
        return shardingConditions.getConditions().isEmpty()
                ? route0(shardingRule, tableRule, Collections.emptyList(), Collections.emptyList())
                : routeByShardingConditionsWithCondition(shardingRule, tableRule); // 按condition分片
    }

    private Collection<DataNode> routeByShardingConditionsWithCondition(final ShardingRule shardingRule, final TableRule tableRule) {
        Collection<DataNode> result = new LinkedList<>();
        // 遍历分片条件列表,插入多少条数据,shardingConditions.getConditions()的size就等于多少。
        for (ShardingCondition each : shardingConditions.getConditions()) {

            // 处理要插入的某行数据
            Collection<DataNode> dataNodes = route0(shardingRule, tableRule,
                    getShardingValuesFromShardingConditions( // !!!
                            shardingRule,
                            shardingRule.getDatabaseShardingStrategy(tableRule).getShardingColumns(), // 某表格决定《分库》的column列表
                            each
                    ),
                    getShardingValuesFromShardingConditions(
                            shardingRule,
                            shardingRule.getTableShardingStrategy(tableRule).getShardingColumns(), // 某表格决定《分表》的column列表
                            each
                    )
            );
            result.addAll(dataNodes);
            originalDataNodes.add(dataNodes);
        }
        return result;
    }

    private Collection<DataNode> routeByMixedConditions(final ShardingRule shardingRule, final TableRule tableRule) {
        return shardingConditions.getConditions().isEmpty() ? routeByMixedConditionsWithHint(shardingRule, tableRule) : routeByMixedConditionsWithCondition(shardingRule, tableRule);
    }

    private Collection<DataNode> routeByMixedConditionsWithCondition(final ShardingRule shardingRule, final TableRule tableRule) {
        Collection<DataNode> result = new LinkedList<>();
        for (ShardingCondition each : shardingConditions.getConditions()) {
            Collection<DataNode> dataNodes = route0(shardingRule, tableRule, getDatabaseShardingValues(shardingRule, tableRule, each), getTableShardingValues(shardingRule, tableRule, each));
            result.addAll(dataNodes);
            originalDataNodes.add(dataNodes);
        }
        return result;
    }

    private Collection<DataNode> routeByMixedConditionsWithHint(final ShardingRule shardingRule, final TableRule tableRule) {
        if (shardingRule.getDatabaseShardingStrategy(tableRule) instanceof HintShardingStrategy) {
            return route0(shardingRule, tableRule, getDatabaseShardingValuesFromHint(), Collections.emptyList());
        }
        return route0(shardingRule, tableRule, Collections.emptyList(), getTableShardingValuesFromHint());
    }

    private List<RouteValue> getDatabaseShardingValues(final ShardingRule shardingRule, final TableRule tableRule, final ShardingCondition shardingCondition) {
        ShardingStrategy dataBaseShardingStrategy = shardingRule.getDatabaseShardingStrategy(tableRule);
        return isGettingShardingValuesFromHint(dataBaseShardingStrategy)
                ? getDatabaseShardingValuesFromHint() : getShardingValuesFromShardingConditions(shardingRule, dataBaseShardingStrategy.getShardingColumns(), shardingCondition);
    }

    private List<RouteValue> getTableShardingValues(final ShardingRule shardingRule, final TableRule tableRule, final ShardingCondition shardingCondition) {
        ShardingStrategy tableShardingStrategy = shardingRule.getTableShardingStrategy(tableRule);
        return isGettingShardingValuesFromHint(tableShardingStrategy)
                ? getTableShardingValuesFromHint() : getShardingValuesFromShardingConditions(shardingRule, tableShardingStrategy.getShardingColumns(), shardingCondition);
    }

    private boolean isGettingShardingValuesFromHint(final ShardingStrategy shardingStrategy) {
        return shardingStrategy instanceof HintShardingStrategy;
    }

    private List<RouteValue> getDatabaseShardingValuesFromHint() {
        return getRouteValues(HintManager.isDatabaseShardingOnly() ? HintManager.getDatabaseShardingValues() : HintManager.getDatabaseShardingValues(logicTableName));
    }

    private List<RouteValue> getTableShardingValuesFromHint() {
        return getRouteValues(HintManager.getTableShardingValues(logicTableName));
    }

    private List<RouteValue> getRouteValues(final Collection<Comparable<?>> shardingValue) {
        return shardingValue.isEmpty() ? Collections.emptyList() : Collections.singletonList(new ListRouteValue<>("", logicTableName, shardingValue));
    }

    private List<RouteValue> getShardingValuesFromShardingConditions(final ShardingRule shardingRule, final Collection<String> shardingColumns, final ShardingCondition shardingCondition) {
        List<RouteValue> result = new ArrayList<>(shardingColumns.size());
        // shardingCondition ===  要插入的某行数据
        // shardingCondition.getRouteValues() === 要插入行的《决定分片的值列表》
        for (RouteValue each : shardingCondition.getRouteValues()) {
            Optional<BindingTableRule> bindingTableRule = shardingRule.findBindingTableRule(logicTableName);

            // 表名 && 字段命中
            if ((logicTableName.equals(each.getTableName()) || bindingTableRule.isPresent() && bindingTableRule.get().hasLogicTable(logicTableName))
                    && shardingColumns.contains(each.getColumnName())) {
                result.add(each);
            }
        }
        return result;
    }

    /**
     * 处理要插入的某行数据
     */
    private Collection<DataNode> route0(final ShardingRule shardingRule, final TableRule tableRule, final List<RouteValue> databaseShardingValues, final List<RouteValue> tableShardingValues) {
        // databaseShardingValues === 影响《分库》的的值列表
        // tableShardingValues === 影响《分表》的值列表

        // 路由数据源
        Collection<String> routedDataSources = routeDataSources(shardingRule, tableRule, databaseShardingValues);

        // 路由表
        Collection<DataNode> result = new LinkedList<>();
        for (String each : routedDataSources) { // 遍历数据源列表
            result.addAll(
                    routeTables(shardingRule, tableRule, each, tableShardingValues) // !!!
            );
        }
        return result;
    }

    private Collection<String> routeDataSources(final ShardingRule shardingRule, final TableRule tableRule, final List<RouteValue> databaseShardingValues) {
        if (databaseShardingValues.isEmpty()) { // 没有值,就使用支持的《所有数据源列表》
            return tableRule.getActualDatasourceNames();
        }

        Collection<String> result = new LinkedHashSet<>(
                // 获取《分库策略》执行分库
                shardingRule.getDatabaseShardingStrategy(tableRule).doSharding(
                        tableRule.getActualDatasourceNames(), // 支持的《所有数据源列表》
                        databaseShardingValues, // 影响分库的值列表
                        this.properties
                )
        );
        Preconditions.checkState(!result.isEmpty(), "no database route info");
        Preconditions.checkState(tableRule.getActualDatasourceNames().containsAll(result),
                "Some routed data sources do not belong to configured data sources. routed data sources: `%s`, configured data sources: `%s`", result, tableRule.getActualDatasourceNames());
        return result;
    }

    private Collection<DataNode> routeTables(final ShardingRule shardingRule, final TableRule tableRule, final String routedDataSource, final List<RouteValue> tableShardingValues) {
        // routedDataSource === 要分表的数据源

        // 获取某个数据源下支持的《所有表列表》
        Collection<String> availableTargetTables = tableRule.getActualTableNames(routedDataSource);

        Collection<String> routedTables = new LinkedHashSet<>(
                tableShardingValues.isEmpty() ?
                        // 影响《分表》的值列表为空,就路由到《所有表列表》
                        availableTargetTables
                        // 获取《分表策略》执行分表
                        : shardingRule.getTableShardingStrategy(tableRule).doSharding(
                        availableTargetTables, // 支持的《所有表列表》
                        tableShardingValues, // 影响《分表》的值列表
                        this.properties
                )
        );
        Preconditions.checkState(!routedTables.isEmpty(), "no table route info");
        Collection<DataNode> result = new LinkedList<>();
        for (String each : routedTables) {
            // routedDataSource === 数据源名称
            // each === 对应的真实表名称
            result.add(new DataNode(routedDataSource, each));
        }
        return result;
    }
}

.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值