溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Sharding-JDBC的架構(gòu)以及源碼的示例分析

發(fā)布時間:2021-10-09 11:44:59 來源:億速云 閱讀:341 作者:柒染 欄目:大數(shù)據(jù)

Sharding-JDBC的架構(gòu)以及源碼的示例分析,針對這個問題,這篇文章詳細(xì)介紹了相對應(yīng)的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

Sharding-jdbc架構(gòu)

Sharding-JDBC的架構(gòu)以及源碼的示例分析

Sharding-jdbc 系統(tǒng)架構(gòu)分成5個部分:

  1. SQL解析

  2. SQL路由

  3. SQL改寫

  4. SQL執(zhí)行

  5. 結(jié)果集歸并

下面從上面五個部分來分析Sharding-jdbc

功能模塊

SQL解析

SQL路由

SQL路由序列圖

Sharding-JDBC的架構(gòu)以及源碼的示例分析

調(diào)用鏈

ShardingPreparedStatement.execute

執(zhí)行方法

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

方法源碼

@Override
    public boolean execute() throws SQLException {
        try {
		//本地緩存清空
            clearPrevious();
		/**
		 * 路由
		 *
		 */
            shard();
		// 初始化 preparedStatement
            initPreparedStatementExecutor();
		// 執(zhí)行sql
            return preparedStatementExecutor.execute();
        } finally {
            clearBatch();
        }
    }
BaseShardingEngine.shard
org.apache.shardingsphere.core.BaseShardingEngine.shard(String, List<Object>)
 public SQLRouteResult shard(final String sql, final List<Object> parameters) {
        List<Object> clonedParameters = cloneParameters(parameters);
		// 根據(jù)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

一些路由相關(guān)的hook在這里執(zhí)行。

org.apache.shardingsphere.core.BaseShardingEngine.executeRoute(String, List<Object>)
 private SQLRouteResult executeRoute(final String sql, final List<Object> 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<Object>)
    public SQLRouteResult route(final List<Object> parameters) {
        if (null == sqlStatement) {
		// 解析SQL
            sqlStatement = shardingRouter.parse(logicSQL, true);
        }
		/**
		 * 第一步:根據(jù)上面異步解析出來的sqlStatement,結(jié)合配置的路由規(guī)則,找到對應(yīng)的物理表表名
		 * 第二步:這里是主從(讀寫)路由,根據(jù)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) {
        ……
		// 創(chuàng)建一個根據(jù)數(shù)據(jù)庫匹配的解析引擎,解析sql。比如mysql的sql創(chuàng)建mysql的數(shù)據(jù)解析引擎。
        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<SQLSegment> sqlSegments = extractorEngine.extract(ast);
        Map<ParserRuleContext, Integer> parameterMarkerIndexes = ast.getParameterMarkerIndexes();
        return fillerEngine.fill(sqlSegments, parameterMarkerIndexes.size(), ast.getSqlStatementRule());
    }
ParsingSQLRouter.route ( 重要)
org.apache.shardingsphere.core.route.router.sharding.ParsingSQLRouter.route(String, List<Object>, SQLStatement)
 public SQLRouteResult route(final String logicSQL, final List<Object> parameters, final SQLStatement sqlStatement) {
 	/**
	 * 根據(jù)sql類型,生成不同的優(yōu)化引擎。比如我這里調(diào)試用的是select語句,生成就是ShardingSelectOptimizeEngine 實例。
	 * 對 語句進(jìn)行優(yōu)化
	 */
        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數(shù)目為1,或者所有的表都是有綁定關(guān)系的)
		 *  接著執(zhí)行 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、根據(jù)邏輯表名去拿分表規(guī)則
		 * 2、根據(jù)分表規(guī)則 去拿DataNode(key 為 dataSourceName,value 為物理表表名)。
		 * 3、將上面的 dataNode 封裝成 RoutingResult
		 */
        return generateRoutingResult(getDataNodes(shardingRule.getTableRule(logicTableName)));
    }

SQL改寫

SQL執(zhí)行

關(guān)于Sharding-JDBC的架構(gòu)以及源碼的示例分析問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI