sharding-jdbc源碼解析之多庫表sql路由

sharding-jdbc多庫多表路由sql

本文轉自「天河聊技術」微信公衆號微信

 

找到這個類com.dangdang.ddframe.rdb.sharding.routing.PreparedStatementRoutingEngineapp

 

找到這裏分佈式

/**
 * SQL路由.
 * 當第一次路由時進行SQL解析,以後的路由複用第一次的解析結果.
 * 
 * @param parameters SQL中的參數
 * @return 路由結果
 */
public SQLRouteResult route(final List<Object> parameters) {//sql路由業務方法
    if (null == sqlStatement) {
        sqlStatement = sqlRouter.parse(logicSQL, parameters.size());
    }
    return sqlRouter.route(logicSQL, parameters, sqlStatement);
}
return sqlRouter.route(logicSQL, parameters, sqlStatement);
@Override
    public SQLRouteResult route(final String logicSQL, final List<Object> parameters, final SQLStatement sqlStatement) {
        final Context context = MetricsContext.start("Route SQL");
        SQLRouteResult result = new SQLRouteResult(sqlStatement);
//        若是是insert語句去生成分佈式逐漸的邏輯
        if (sqlStatement instanceof InsertStatement && null != ((InsertStatement) sqlStatement).getGeneratedKey()) {
            processGeneratedKey(parameters, (InsertStatement) sqlStatement, result);
        }
        RoutingResult routingResult = route(parameters, sqlStatement);
RoutingResult routingResult = route(parameters, sqlStatement);
private RoutingResult route(final List<Object> parameters, final SQLStatement sqlStatement) {
        Collection<String> tableNames = sqlStatement.getTables().getTableNames();
        RoutingEngine routingEngine;
//        若是表集合是1,或者是綁定表路由就走簡單路由規則
        if (1 == tableNames.size() || shardingRule.isAllBindingTables(tableNames)) {
            routingEngine = new SimpleRoutingEngine(shardingRule, parameters, tableNames.iterator().next(), sqlStatement);//單表路由
        } else {
            // TODO 可配置是否執行笛卡爾積
            routingEngine = new ComplexRoutingEngine(shardingRule, parameters, tableNames, sqlStatement);
        }
        return routingEngine.route();//tianhe TODO 笛卡爾積
    }

進入到這個方法com.dangdang.ddframe.rdb.sharding.routing.type.complex.ComplexRoutingEngine.route()ide

@Override
    public RoutingResult route() {
        Collection<RoutingResult> result = new ArrayList<>(logicTables.size());
        Collection<String> bindingTableNames = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
        for (String each : logicTables) {
//            根據邏輯表查找分片規則
            Optional<TableRule> tableRule = shardingRule.tryFindTableRule(each);
            if (tableRule.isPresent()) {
//                若是綁定表名不包含邏輯表走簡單路由
                if (!bindingTableNames.contains(each)) {
                    result.add(new SimpleRoutingEngine(shardingRule, parameters, tableRule.get().getLogicTable(), sqlStatement).route());
                }
//                根據邏輯表找綁定表規則配置,若是有走綁定表規則配置路由
                Optional<BindingTableRule> bindingTableRule = shardingRule.findBindingTableRule(each);
                if (bindingTableRule.isPresent()) {
                    bindingTableNames.addAll(Lists.transform(bindingTableRule.get().getTableRules(), new Function<TableRule, String>() {
                        
                        @Override
                        public String apply(final TableRule input) {
                            return input.getLogicTable();
                        }
                    }));
                }
            }
        }
        log.trace("mixed tables sharding result: {}", result);
        if (result.isEmpty()) {
            throw new ShardingJdbcException("Cannot find table rule and default data source with logic tables: '%s'", logicTables);
        }
        if (1 == result.size()) {
            return result.iterator().next();
        }
//        建立混合多庫表路由結果
        return new CartesianRoutingEngine(result).route();
    }
return new CartesianRoutingEngine(result).route();

笛卡爾積路由引擎ui

/**
 * 笛卡爾積的庫表路由.
 * 
 * @author zhangliang
 */
@RequiredArgsConstructor
@Slf4j
public final class CartesianRoutingEngine implements RoutingEngine {
    
//    路由結果
    private final Collection<RoutingResult> routingResults;

 

返回到這裏orm

@Override
    public CartesianRoutingResult route() {
//        建立笛卡爾積路由對象
        CartesianRoutingResult result = new CartesianRoutingResult();
//        遍歷數據源和邏輯表集合的映射關係
        for (Entry<String, Set<String>> entry : getDataSourceLogicTablesMap().entrySet()) {
//            獲取物理表集合
            List<Set<String>> actualTableGroups = getActualTableGroups(entry.getKey(), entry.getValue());
//            根據數據源和物理表集合獲取具體的執行單元
            List<Set<TableUnit>> tableUnitGroups = toTableUnitGroups(entry.getKey(), actualTableGroups);
            result.merge(entry.getKey(), getCartesianTableReferences(Sets.cartesianProduct(tableUnitGroups)));
        }
        log.trace("cartesian tables sharding result: {}", result);
        return result;
    }
組裝笛卡爾積結果集
Sets.cartesianProduct(tableUnitGroups)

 

組裝笛卡爾積路由組對象

getCartesianTableReferences(Sets.cartesianProduct(tableUnitGroups))

組裝笛卡爾積路由結果對象路由

result.merge

以上介紹了多庫表、笛卡爾積路由。get

向上返回到這裏

@Override
    public SQLRouteResult route(final String logicSQL, final List<Object> parameters, final SQLStatement sqlStatement) {
        final Context context = MetricsContext.start("Route SQL");
        SQLRouteResult result = new SQLRouteResult(sqlStatement);
//        若是是insert語句去生成分佈式逐漸的邏輯
        if (sqlStatement instanceof InsertStatement && null != ((InsertStatement) sqlStatement).getGeneratedKey()) {
            processGeneratedKey(parameters, (InsertStatement) sqlStatement, result);
        }
//        進行sql路由返回路由結果
        RoutingResult routingResult = route(parameters, sqlStatement);
        SQLRewriteEngine rewriteEngine = new SQLRewriteEngine(shardingRule, logicSQL, sqlStatement);
        boolean isSingleRouting = routingResult.isSingleRouting();
        if (sqlStatement instanceof SelectStatement && null != ((SelectStatement) sqlStatement).getLimit()) {
            processLimit(parameters, (SelectStatement) sqlStatement, isSingleRouting);
        }
        SQLBuilder sqlBuilder = rewriteEngine.rewrite(!isSingleRouting);
        if (routingResult instanceof CartesianRoutingResult) {
            for (CartesianDataSource cartesianDataSource : ((CartesianRoutingResult) routingResult).getRoutingDataSources()) {
                for (CartesianTableReference cartesianTableReference : cartesianDataSource.getRoutingTableReferences()) {
                    result.getExecutionUnits().add(new SQLExecutionUnit(cartesianDataSource.getDataSource(), rewriteEngine.generateSQL(cartesianTableReference, sqlBuilder)));
                }
            }
        } else {
            for (TableUnit each : routingResult.getTableUnits().getTableUnits()) {
                result.getExecutionUnits().add(new SQLExecutionUnit(each.getDataSourceName(), rewriteEngine.generateSQL(each, sqlBuilder)));
            }
        }
        MetricsContext.stop(context);
        if (showSQL) {
            SQLLogger.logSQL(logicSQL, sqlStatement, result.getExecutionUnits(), parameters);
        }
        return result;
    }

後面的是sql重寫的部分下次介紹。

 

說到最後

以上是混合多庫多表路由源碼解析,僅供參考。

相關文章
相關標籤/搜索