ShardingSphere的路由流程
ShardingSphere的路由流程
本篇文章源码基于4.0.1版本
ShardingSphere的分片引擎从解析引擎到路由引擎到改写引擎到执行引擎再到归并引擎,一步一步对分片操作进行处理,我们这篇文章先从解析引擎开始,深入分析一下Sql的解析引擎处理流程。
路由的入口
ShardingStatement是支持分片的Statement,以它的executeQuery()执行查询操作的方法为入口,看看分片路由做了什么。这里调用自身的shard()方法进行分片,这个方法中创建SimpleQueryShardingEngine对象,
SimpleQueryShardingEngine继承了抽象类BaseShardingEngine,作用就是用于简单查询的分片引擎,创建完对象信息后调用shard()方法进行分片,核心操作是BaseShardingEngine的子类实现的route()方法,这里是模板方法的体现:先进行准备参数,然后执行路由,然后进行Sql的转换和改写,其中准备参数的方法和执行路由的方法由子类实现,它的子类有SimpleQueryShardingEngine和PreparedQueryShardingEngine,这里用到的是SimpleQueryShardingEngine,SimpleQueryShardingEngine的路由方法中直接调用了语句路由引擎类StatementRoutingEngine
StatementRoutingEngine的route()方法:
public SQLRouteResult route(final String logicSQL) {
SQLStatement sqlStatement = shardingRouter.parse(logicSQL, false);
return masterSlaveRouter.route(shardingRouter.route(logicSQL, Collections.emptyList(), sqlStatement));
}
这里先通过ShardingRouter这个类进行了分片路由,然后通过ShardingMasterSlaveRouter进行主从路由,下面就分片路由这个方法看看它具体是怎么进行路由的
路由流程分析
ShardingRouter的route()方法:
public SQLRouteResult route(final String logicSQL, final List<Object> parameters, final SQLStatement sqlStatement) {
Optional<ShardingStatementValidator> shardingStatementValidator = ShardingStatementValidatorFactory.newInstance(sqlStatement);
if (shardingStatementValidator.isPresent()) {
shardingStatementValidator.get().validate(shardingRule, sqlStatement, parameters);
}
SQLStatementContext sqlStatementContext = SQLStatementContextFactory.newInstance(metaData.getRelationMetas(), logicSQL, parameters, sqlStatement);
Optional<GeneratedKey> generatedKey = sqlStatement instanceof InsertStatement
? GeneratedKey.getGenerateKey(shardingRule, metaData.getTables(), parameters, (InsertStatement) sqlStatement) : Optional.<GeneratedKey>absent();
ShardingConditions shardingConditions = getShardingConditions(parameters, sqlStatementContext, generatedKey.orNull(), metaData.getRelationMetas());
boolean needMergeShardingValues = isNeedMergeShardingValues(sqlStatementContext);
if (sqlStatementContext.getSqlStatement() instanceof DMLStatement && needMergeShardingValues) {
checkSubqueryShardingValues(sqlStatementContext, shardingConditions);
mergeShardingConditions(shardingConditions);
}
RoutingEngine routingEngine = RoutingEngineFactory.newInstance(shardingRule, metaData, sqlStatementContext, shardingConditions);
RoutingResult routingResult = routingEngine.route();
if (needMergeShardingValues) {
Preconditions.checkState(1 == routingResult.getRoutingUnits().size(), "Must have one sharding with subquery.");
}
SQLRouteResult result = new SQLRouteResult(sqlStatementContext, shardingConditions, generatedKey.orNull());
result.setRoutingResult(routingResult);
if (sqlStatementContext instanceof InsertSQLStatementContext) {
setGeneratedValues(result);
}
return result;
}
- 利用ShardingStatementValidatorFactory分片语句验证器工厂类创建ShardingStatementValidator分片语句验证器对象,校验器校验的是InsertStatement和UpdateStatement这两类SQL语句,校验器功能就是校验SQL语句是否支持分片操作,当判断存在重复的键值列并且这个列是分片键的时候检验不通过
- 获取Sql语句的上下文,同样是使用了SQLStatementContextFactory工厂类创建SQLStatementContext实例,SQLStatementContext的主要功能就是一个承上启下的作用,用来进行数据的存储和传递
- 判断SQL语句是否为插入语句,如果是的话调用GeneratedKey类来生成主键,生成主键的逻辑我们前面的文章分析了,支持UUID、雪花算法等
- 获取分片条件,具体来说判断语句上下文对象,如果是插入语句的上下文,通过用于插入子句的分片条件引擎InsertClauseShardingConditionEngine创建分片条件,否则使用where 子句的分片条件引擎WhereClauseShardingConditionEngine创建分片条件
- 判断是否需要进行合并分片条件操作,如果是DML语句并且需要合并的话,调用mergeShardingConditions()方法进行分片条件合并
- 执行路由,这里是核心代码,同样使用了工厂模式,路由引擎工厂类RoutingEngineFactory创建路由引擎,执行完路由后路由结果对象RoutingResult对象,路由引擎有很多种,不同的路由策略对应不同的路由引擎。
- 构建SQLRouteResult对象,将RoutingResult对象设置到了SQLRouteResult对象中,填充自动生成的分片键,返回结果。
总结
这篇文章主要讲了ShardingSphere的路由流程,入口以ShardingStatement的执行查询操作的方法为入口,最终定位到路由流程是ShardingRouter的route()方法,这个方法中大致先进行校验是否可以分片操作,然后创建Sql语句的上下文,判断是否需要生成主键,获取分片条件,判断是否需要合并分片条件,最终选择不同的路由引擎执行路由操作,将路由结果对象包装成SQLRouteResult对象并返回。
- 点赞
- 收藏
- 关注作者
评论(0)