189 8069 5689

Sharding-JDBC的架构以及源码的示例分析

Sharding-JDBC的架构以及源码的示例分析,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

10年积累的成都网站设计、网站制作经验,可以快速应对客户对网站的新想法和需求。提供各种问题对应的解决方案。让选择我们的客户得到更好、更有力的网络服务。我虽然不认识你,你也不认识我。但先建设网站后付款的网站建设流程,更有静安免费网站建设让你可以放心的选择与我们合作。

Sharding-jdbc架构

Sharding-JDBC的架构以及源码的示例分析

Sharding-jdbc 系统架构分成5个部分:

  1. SQL解析

  2. SQL路由

  3. SQL改写

  4. SQL执行

  5. 结果集归并

下面从上面五个部分来分析Sharding-jdbc

功能模块

SQL解析

SQL路由

SQL路由序列图

Sharding-JDBC的架构以及源码的示例分析

调用链

ShardingPreparedStatement.execute

执行方法

org.apache.shardingsphere.shardingjdbc.jdbc.core.statement.ShardingPreparedStatement.execute()

方法源码

@Override
    public boolean execute() throws SQLException {
        try {
		//本地缓存清空
            clearPrevious();
		/**
		 * 路由
		 *
		 */
            shard();
		// 初始化 preparedStatement
            initPreparedStatementExecutor();
		// 执行sql
            return preparedStatementExecutor.execute();
        } finally {
            clearBatch();
        }
    }
BaseShardingEngine.shard
org.apache.shardingsphere.core.BaseShardingEngine.shard(String, List)
 public SQLRouteResult shard(final String sql, final List parameters) {
        List clonedParameters = cloneParameters(parameters);
		// 根据SQL去路由
        SQLRouteResult result = executeRoute(sql, clonedParameters);
		// 改写sql
        result.getRouteUnits().addAll(HintManager.isDatabaseShardingOnly() ? convert(sql, clonedParameters, result) : rewriteAndConvert(sql, clonedParameters, result));
		// 打印路由后的sql
        if (shardingProperties.getValue(ShardingPropertiesConstant.SQL_SHOW)) {
            boolean showSimple = shardingProperties.getValue(ShardingPropertiesConstant.SQL_SIMPLE);
            SQLLogger.logSQL(sql, showSimple, result.getShardingStatement(), result.getRouteUnits());
        }
        return result;
    }
BaseShardingEngine.executeRoute

一些路由相关的hook在这里执行。

org.apache.shardingsphere.core.BaseShardingEngine.executeRoute(String, List)
 private SQLRouteResult executeRoute(final String sql, final List clonedParameters) {
        routingHook.start(sql);
        try {
            SQLRouteResult result = route(sql, clonedParameters);
            routingHook.finishSuccess(result, metaData.getTables());
            return result;
            // CHECKSTYLE:OFF
        } catch (final Exception ex) {
            // CHECKSTYLE:ON
            routingHook.finishFailure(ex);
            throw ex;
        }
    }
PreparedStatementRoutingEngine.route
org.apache.shardingsphere.core.route.PreparedStatementRoutingEngine.route(List)
    public SQLRouteResult route(final List parameters) {
        if (null == sqlStatement) {
		// 解析SQL
            sqlStatement = shardingRouter.parse(logicSQL, true);
        }
		/**
		 * 第一步:根据上面异步解析出来的sqlStatement,结合配置的路由规则,找到对应的物理表表名
		 * 第二步:这里是主从(读写)路由,根据sql的类型(select、DML)决定走主库还是从库。
		 */
        return masterSlaveRouter.route(shardingRouter.route(logicSQL, parameters, sqlStatement));
    }
SQLParseEngine.parse0
org.apache.shardingsphere.core.parse.SQLParseEngine.parse0(String, boolean)
private SQLStatement parse0(final String sql, final boolean useCache) {
        ……
		// 创建一个根据数据库匹配的解析引擎,解析sql。比如MySQL的sql创建mysql的数据解析引擎。
        SQLStatement result = new SQLParseKernel(ParseRuleRegistry.getInstance(), databaseType, sql).parse();
        if (useCache) {
            cache.put(sql, result);
        }
        return result;
    }
SQLParseKernel.parse

这个是解析sql。这个方法不再深入了。

org.apache.shardingsphere.core.parse.core.SQLParseKernel.parse()
    public SQLStatement parse() {
	// 解析sql
        SQLAST ast = parserEngine.parse();
	// 抽取sql 片段
        Collection sqlSegments = extractorEngine.extract(ast);
        Map parameterMarkerIndexes = ast.getParameterMarkerIndexes();
        return fillerEngine.fill(sqlSegments, parameterMarkerIndexes.size(), ast.getSqlStatementRule());
    }
ParsingSQLRouter.route ( 重要)
org.apache.shardingsphere.core.route.router.sharding.ParsingSQLRouter.route(String, List, SQLStatement)
 public SQLRouteResult route(final String logicSQL, final List parameters, final SQLStatement sqlStatement) {
 	/**
	 * 根据sql类型,生成不同的优化引擎。比如我这里调试用的是select语句,生成就是ShardingSelectOptimizeEngine 实例。
	 * 对 语句进行优化
	 */
        ShardingOptimizedStatement shardingStatement = ShardingOptimizeEngineFactory.newInstance(sqlStatement).optimize(shardingRule, metaData.getTables(), logicSQL, parameters, sqlStatement);
		
        boolean needMergeShardingValues = isNeedMergeShardingValues(shardingStatement);
        if (shardingStatement instanceof ShardingConditionOptimizedStatement && needMergeShardingValues) {
            checkSubqueryShardingValues(shardingStatement, ((ShardingConditionOptimizedStatement) shardingStatement).getShardingConditions());
            mergeShardingConditions(((ShardingConditionOptimizedStatement) shardingStatement).getShardingConditions());
        }
		/**
		 *  这里获取一个路由引擎,这里有各种引擎,常见的有 StandardRoutingEngine、ComplexRoutingEngine
		 *  这次获取的就是 获取一个 StandardRoutingEngine 路由引擎。(shardingtable数目为1,或者所有的表都是有绑定关系的)
		 *  接着执行 StandardRoutingEngine.route方法
		 *
		 */
        RoutingResult routingResult = RoutingEngineFactory.newInstance(shardingRule, metaData.getDataSources(), shardingStatement).route();
        if (needMergeShardingValues) {
            Preconditions.checkState(1 == routingResult.getRoutingUnits().size(), "Must have one sharding with subquery.");
        }
		// 分布式主键插入
        if (shardingStatement instanceof ShardingInsertOptimizedStatement) {
            setGeneratedValues((ShardingInsertOptimizedStatement) shardingStatement);
        }
		// 加密
        EncryptOptimizedStatement encryptStatement = EncryptOptimizeEngineFactory.newInstance(sqlStatement)
                .optimize(shardingRule.getEncryptRule(), metaData.getTables(), logicSQL, parameters, sqlStatement);
        SQLRouteResult result = new SQLRouteResult(shardingStatement, encryptStatement);
        result.setRoutingResult(routingResult);
        return result;
    }
StandardRoutingEngine.route(重要)
org.apache.shardingsphere.core.route.type.standard.StandardRoutingEngine.route()
public RoutingResult route() {
        if (isDMLForModify(optimizedStatement.getSQLStatement()) && !optimizedStatement.getTables().isSingleTable()) {
            throw new ShardingException("Cannot support Multiple-Table for '%s'.", optimizedStatement.getSQLStatement());
        }
		/**
		 * 1、根据逻辑表名去拿分表规则
		 * 2、根据分表规则 去拿DataNode(key 为 dataSourceName,value 为物理表表名)。
		 * 3、将上面的 dataNode 封装成 RoutingResult
		 */
        return generateRoutingResult(getDataNodes(shardingRule.getTableRule(logicTableName)));
    }

SQL改写

SQL执行

关于Sharding-JDBC的架构以及源码的示例分析问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注创新互联行业资讯频道了解更多相关知识。


分享标题:Sharding-JDBC的架构以及源码的示例分析
标题URL:http://jkwzsj.com/article/gocchj.html