sharding-jdbc源码解析之多库表sql路由

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

sharding-jdbc多库多表路由

本文转自“天河聊技术”微信公众号

 

找到这个类com.dangdang.ddframe.rdb.sharding.routing.PreparedStatementRoutingEngine

 

找到这里

/**
 * SQL路由.
 * 当第一次路由时进行SQL解析,之后的路由复用第一次的解析结果.
 * 
 * @param parameters SQL中的参数
 * @return 路由结果
 */
public SQLRouteResult route(final List 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 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 parameters, final SQLStatement sqlStatement) {
        Collection 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()

@Override
    public RoutingResult route() {
        Collection result = new ArrayList<>(logicTables.size());
        Collection bindingTableNames = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
        for (String each : logicTables) {
//            根据逻辑表查找分片规则
            Optional tableRule = shardingRule.tryFindTableRule(each);
            if (tableRule.isPresent()) {
//                如果绑定表名不包含逻辑表走简单路由
                if (!bindingTableNames.contains(each)) {
                    result.add(new SimpleRoutingEngine(shardingRule, parameters, tableRule.get().getLogicTable(), sqlStatement).route());
                }
//                根据逻辑表找绑定表规则配置,如果有走绑定表规则配置路由
                Optional bindingTableRule = shardingRule.findBindingTableRule(each);
                if (bindingTableRule.isPresent()) {
                    bindingTableNames.addAll(Lists.transform(bindingTableRule.get().getTableRules(), new Function() {
                        
                        @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();

笛卡尔积路由引擎

/**
 * 笛卡尔积的库表路由.
 * 
 * @author zhangliang
 */
@RequiredArgsConstructor
@Slf4j
public final class CartesianRoutingEngine implements RoutingEngine {
    
//    路由结果
    private final Collection routingResults;

 

返回到这里

@Override
    public CartesianRoutingResult route() {
//        创建笛卡尔积路由对象
        CartesianRoutingResult result = new CartesianRoutingResult();
//        遍历数据源和逻辑表集合的映射关系
        for (Entry> entry : getDataSourceLogicTablesMap().entrySet()) {
//            获取物理表集合
            List> actualTableGroups = getActualTableGroups(entry.getKey(), entry.getValue());
//            根据数据源和物理表集合获取具体的执行单元
            List> 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

以上介绍了多库表、笛卡尔积路由。

向上返回到这里

@Override
    public SQLRouteResult route(final String logicSQL, final List 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重写的部分下次介绍。

 

说到最后

以上是混合多库多表路由源码解析,仅供参考。

转载于:https://my.oschina.net/u/3775437/blog/1785009

你可能感兴趣的:(sharding-jdbc源码解析之多库表sql路由)