在sql路由过程中,是通过sql路由引擎ShardingRouter完成的,定义如下:
public interface ShardingRouter {
//解析
SQLStatement parse(String logicSQL, boolean useCache);
//路由
SQLRouteResult route(String logicSQL, List
可以看到,sql路由解析分为两块,一块做解析,一块做路由。实现类有两个,一个是指定数据库路由DatabaseHintSQLRouter,一个是解析sql路由ParsingSQLRouter。
sql路由在StatementRoutingEngine中被调用,根据参数,选择不同的sql路由解析器解析和做路由。
public final class StatementRoutingEngine {
private final ShardingRouter shardingRouter;
private final ShardingMasterSlaveRouter masterSlaveRouter;
public StatementRoutingEngine(final ShardingRule shardingRule, final ShardingMetaData shardingMetaData, final DatabaseType databaseType, final boolean showSQL) {
//创建sharding路由引擎
shardingRouter = ShardingRouterFactory.createSQLRouter(shardingRule, shardingMetaData, databaseType, showSQL);
//主备数据库路由引擎
masterSlaveRouter = new ShardingMasterSlaveRouter(shardingRule.getMasterSlaveRules());
}
public SQLRouteResult route(final String logicSQL) {
//语法解析
SQLStatement sqlStatement = shardingRouter.parse(logicSQL, false);
//路由规则路由
return masterSlaveRouter.route(shardingRouter.route(logicSQL, Collections.emptyList(), sqlStatement));
}
}
这里以sql语法路由解析器为例,看一下sharding-sphere如何做解析。
//ParsingSQLRouter.java
@Override
public SQLRouteResult route(final String logicSQL, final List
可以看到,在sql路由解析过程中,经过了四个过程,一个是sql优化器优化sql查询或插入条件,路由,sql重写,最后组装执行单元并返回。
这里重点关注路由,sql优化和sql重写后续再看。
private RoutingResult route(final List
可以看到,在路由过程中,判断sqlStatement的类型,和数据库实体表类型选择不同的sql路由引擎路由。
以 UnicastRoutingEngine路由为例,看一下路由过程:
public final class UnicastRoutingEngine implements RoutingEngine {
private final ShardingRule shardingRule;
private final Collection logicTables;
@Override
public RoutingResult route() {
RoutingResult result = new RoutingResult();
if (logicTables.isEmpty()) {
//如果表为null,则组装表数据单元,不组装RoutingTable
result.getTableUnits().getTableUnits().add(new TableUnit(shardingRule.getShardingDataSourceNames().getDataSourceNames().iterator().next()));
} else if (1 == logicTables.size()) {
//如果只有一张表,则组装表数据单元,和单个表的路由表规则RoutingTable
String logicTableName = logicTables.iterator().next();
DataNode dataNode = shardingRule.findDataNode(logicTableName);
TableUnit tableUnit = new TableUnit(dataNode.getDataSourceName());
tableUnit.getRoutingTables().add(new RoutingTable(logicTableName, dataNode.getTableName()));
result.getTableUnits().getTableUnits().add(tableUnit);
} else {
//如果多个实体表,则组装表数据单元,和单个表的路由表规则RoutingTable
String dataSourceName = null;
List routingTables = new ArrayList<>(logicTables.size());
for (String each : logicTables) {
DataNode dataNode = shardingRule.findDataNode(dataSourceName, each);
routingTables.add(new RoutingTable(each, dataNode.getTableName()));
if (null == dataSourceName) {
dataSourceName = dataNode.getDataSourceName();
}
}
TableUnit tableUnit = new TableUnit(dataSourceName);
//添加RoutingTables
tableUnit.getRoutingTables().addAll(routingTables);
result.getTableUnits().getTableUnits().add(tableUnit);
}
return result;
}
}
可以看到,如果是广播模式,会根据实体表的数量,组装不同的RoutingTable。
再看一个标准路由引擎
public final class StandardRoutingEngine implements RoutingEngine {
private final ShardingRule shardingRule;
private final String logicTableName;
private final ShardingConditions shardingConditions;
@Override
public RoutingResult route() {
//获取表规则
TableRule tableRule = shardingRule.getTableRule(logicTableName);
//获取数据库分片策略
Collection databaseShardingColumns = shardingRule.getDatabaseShardingStrategy(tableRule).getShardingColumns();
//获取表分片策略
Collection tableShardingColumns = shardingRule.getTableShardingStrategy(tableRule).getShardingColumns();
Collection routedDataNodes = new LinkedHashSet<>();
//如果是指定数据库类型
if (HintManagerHolder.isUseShardingHint()) {
List databaseShardingValues = getDatabaseShardingValuesFromHint(databaseShardingColumns);
List tableShardingValues = getTableShardingValuesFromHint(tableShardingColumns);
Collection dataNodes = route(tableRule, databaseShardingValues, tableShardingValues);
for (ShardingCondition each : shardingConditions.getShardingConditions()) {
if (each instanceof InsertShardingCondition) {
((InsertShardingCondition) each).getDataNodes().addAll(dataNodes);
}
}
routedDataNodes.addAll(dataNodes);
} else {
//如果分片条件为null
if (shardingConditions.getShardingConditions().isEmpty()) {
//所有节点添加数据节点
routedDataNodes.addAll(route(tableRule, Collections.emptyList(), Collections.emptyList()));
} else {
for (ShardingCondition each : shardingConditions.getShardingConditions()) {
List databaseShardingValues = getShardingValues(databaseShardingColumns, each);
List tableShardingValues = getShardingValues(tableShardingColumns, each);
//路由
Collection dataNodes = route(tableRule, databaseShardingValues, tableShardingValues);
routedDataNodes.addAll(dataNodes);
if (each instanceof InsertShardingCondition) {
((InsertShardingCondition) each).getDataNodes().addAll(dataNodes);
}
}
}
}
return generateRoutingResult(routedDataNodes);
}
private Collection route(final TableRule tableRule, final List databaseShardingValues, final List tableShardingValues) {
//路由数据库
Collection routedDataSources = routeDataSources(tableRule, databaseShardingValues);
Collection result = new LinkedList<>();
for (String each : routedDataSources) {
result.addAll(routeTables(tableRule, each, tableShardingValues));
}
return result;
}
private List getDatabaseShardingValuesFromHint(final Collection shardingColumns) {
List result = new ArrayList<>(shardingColumns.size());
for (String each : shardingColumns) {
Optional shardingValue = HintManagerHolder.getDatabaseShardingValue(new ShardingKey(logicTableName, each));
if (shardingValue.isPresent()) {
result.add(shardingValue.get());
}
}
return result;
}
private List getTableShardingValuesFromHint(final Collection shardingColumns) {
List result = new ArrayList<>(shardingColumns.size());
for (String each : shardingColumns) {
Optional shardingValue = HintManagerHolder.getTableShardingValue(new ShardingKey(logicTableName, each));
if (shardingValue.isPresent()) {
result.add(shardingValue.get());
}
}
return result;
}
private List getShardingValues(final Collection shardingColumns, final ShardingCondition shardingCondition) {
List result = new ArrayList<>(shardingColumns.size());
for (ShardingValue each : shardingCondition.getShardingValues()) {
if (logicTableName.equals(each.getLogicTableName()) && shardingColumns.contains(each.getColumnName())) {
result.add(each);
}
}
return result;
}
private Collection routeDataSources(final TableRule tableRule, final List databaseShardingValues) {
Collection availableTargetDatabases = tableRule.getActualDatasourceNames();
if (databaseShardingValues.isEmpty()) {
return availableTargetDatabases;
}
Collection result = new LinkedHashSet<>(shardingRule.getDatabaseShardingStrategy(tableRule).doSharding(availableTargetDatabases, databaseShardingValues));
Preconditions.checkState(!result.isEmpty(), "no database route info");
return result;
}
private Collection routeTables(final TableRule tableRule, final String routedDataSource, final List tableShardingValues) {
Collection availableTargetTables = tableRule.getActualTableNames(routedDataSource);
Collection routedTables = new LinkedHashSet<>(tableShardingValues.isEmpty() ? availableTargetTables
: shardingRule.getTableShardingStrategy(tableRule).doSharding(availableTargetTables, tableShardingValues));
Preconditions.checkState(!routedTables.isEmpty(), "no table route info");
Collection result = new LinkedList<>();
for (String each : routedTables) {
result.add(new DataNode(routedDataSource, each));
}
return result;
}
//组装路由结果
private RoutingResult generateRoutingResult(final Collection routedDataNodes) {
RoutingResult result = new RoutingResult();
for (DataNode each : routedDataNodes) {
//新增表单元
TableUnit tableUnit = new TableUnit(each.getDataSourceName());
//添加路由表
tableUnit.getRoutingTables().add(new RoutingTable(logicTableName, each.getTableName()));
result.getTableUnits().getTableUnits().add(tableUnit);
}
return result;
}
}
master-slave路由,根据规则路由。
public SQLRouteResult route(final SQLRouteResult sqlRouteResult) {
for (MasterSlaveRule each : masterSlaveRules) {
route(each, sqlRouteResult);
}
return sqlRouteResult;
}
private void route(final MasterSlaveRule masterSlaveRule, final SQLRouteResult sqlRouteResult) {
Collection toBeRemoved = new LinkedList<>();
Collection toBeAdded = new LinkedList<>();
for (SQLExecutionUnit each : sqlRouteResult.getExecutionUnits()) {
//如果不是配置的数据源名称,则忽略
if (!masterSlaveRule.getName().equalsIgnoreCase(each.getDataSource())) {
continue;
}
//删除该执行单元
toBeRemoved.add(each);
//如果是主
if (isMasterRoute(sqlRouteResult.getSqlStatement().getType())) {
//主节点visited
MasterVisitedManager.setMasterVisited();
toBeAdded.add(new SQLExecutionUnit(masterSlaveRule.getMasterDataSourceName(), each.getSqlUnit()));
} else {
//新增sql执行单元
toBeAdded.add(new SQLExecutionUnit(masterSlaveRule.getLoadBalanceAlgorithm().getDataSource(
masterSlaveRule.getName(), masterSlaveRule.getMasterDataSourceName(), new ArrayList<>(masterSlaveRule.getSlaveDataSourceNames())), each.getSqlUnit()));
}
}
//删除不需要执行的单元
sqlRouteResult.getExecutionUnits().removeAll(toBeRemoved);
//添加需要新增的执行单元
sqlRouteResult.getExecutionUnits().addAll(toBeAdded);
}