序
本文主要研究一下 sharding-jdbc 的 ShardingMasterSlaveRouter
ShardingMasterSlaveRouter
incubator-shardingsphere-4.0.0-RC1/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/router/masterslave/ShardingMasterSlaveRouter.java
@RequiredArgsConstructor
public final class ShardingMasterSlaveRouter {
private final Collection<MasterSlaveRule> masterSlaveRules;
/**
* Route Master slave after sharding.
*
* @param sqlRouteResult SQL route result
* @return route result
*/
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<TableUnit> toBeRemoved = new LinkedList<>();
Collection<TableUnit> toBeAdded = new LinkedList<>();
for (TableUnit each : sqlRouteResult.getRoutingResult().getTableUnits().getTableUnits()) {if (!masterSlaveRule.getName().equalsIgnoreCase(each.getDataSourceName())) {continue;}
toBeRemoved.add(each);
String actualDataSourceName;
if (isMasterRoute(sqlRouteResult.getSqlStatement().getType())) {MasterVisitedManager.setMasterVisited();
actualDataSourceName = masterSlaveRule.getMasterDataSourceName();} else {actualDataSourceName = masterSlaveRule.getLoadBalanceAlgorithm().getDataSource(masterSlaveRule.getName(), masterSlaveRule.getMasterDataSourceName(), new ArrayList<>(masterSlaveRule.getSlaveDataSourceNames()));
}
toBeAdded.add(createNewTableUnit(actualDataSourceName, each));
}
sqlRouteResult.getRoutingResult().getTableUnits().getTableUnits().removeAll(toBeRemoved);
sqlRouteResult.getRoutingResult().getTableUnits().getTableUnits().addAll(toBeAdded);
}
private boolean isMasterRoute(final SQLType sqlType) {return SQLType.DQL != sqlType || MasterVisitedManager.isMasterVisited() || HintManager.isMasterRouteOnly();}
private TableUnit createNewTableUnit(final String actualDataSourceName, final TableUnit originalTableUnit) {TableUnit result = new TableUnit(actualDataSourceName, originalTableUnit.getDataSourceName());
result.getRoutingTables().addAll(originalTableUnit.getRoutingTables());
return result;
}
}
- ShardingMasterSlaveRouter 提供了 route 方法,返回 sqlRouteResult,这里修改了 sqlRouteResult 的 routingResult 的 tableUnits 的 TableUnit 集合
SQLRouteResult
incubator-shardingsphere-4.0.0-RC1/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/SQLRouteResult.java
@RequiredArgsConstructor
@Getter
@Setter
public final class SQLRouteResult {
private final SQLStatement sqlStatement;
private final GeneratedKey generatedKey;
// For multiple thread read cached sqlStatement, clone limit on SQLRouteResult, because limit will be modified after cache
// TODO need more good design here
private Limit limit;
private RoutingResult routingResult;
private OptimizeResult optimizeResult;
private final Collection<RouteUnit> routeUnits = new LinkedHashSet<>();
public SQLRouteResult(final SQLStatement sqlStatement) {this(sqlStatement, null);
}
}
- SQLRouteResult 拥有 RoutingResult 属性
RoutingResult
incubator-shardingsphere-4.0.0-RC1/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/type/RoutingResult.java
@Getter
public class RoutingResult {private final TableUnits tableUnits = new TableUnits();
/**
* Judge is route for single database and table only or not.
*
* @return is route for single database and table only or not
*/
public boolean isSingleRouting() {return 1 == tableUnits.getTableUnits().size();}
}
- RoutingResult 拥有 TableUnits 属性
TableUnits
incubator-shardingsphere-4.0.0-RC1/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/type/TableUnits.java
@Getter
@ToString
public final class TableUnits {private final Collection<TableUnit> tableUnits = new LinkedHashSet<>();
/**
* Get all data source names.
*
* @return all data source names
*/
public Collection<String> getDataSourceNames() {Collection<String> result = new HashSet<>(tableUnits.size(), 1);
for (TableUnit each : tableUnits) {result.add(each.getDataSourceName());
}
return result;
}
/**
* Get routing table via data source name and actual table name.
*
* @param dataSourceName data source name
* @param actualTableName actual table name
* @return routing table
*/
public Optional<RoutingTable> getRoutingTable(final String dataSourceName, final String actualTableName) {for (TableUnit each : tableUnits) {Optional<RoutingTable> result = each.getRoutingTable(dataSourceName, actualTableName);
if (result.isPresent()) {return result;}
}
return Optional.absent();}
/**
* Get actual tables group via data source name and logic tables' names.
* <p>
* Actual tables in same group are belong one logic name.
* </p>
*
* @param dataSourceName data source name
* @param logicTableNames logic tables' names
* @return actual tables group
*/
public List<Set<String>> getActualTableNameGroups(final String dataSourceName, final Set<String> logicTableNames) {List<Set<String>> result = new ArrayList<>();
for (String logicTableName : logicTableNames) {Set<String> actualTableNames = getActualTableNames(dataSourceName, logicTableName);
if (!actualTableNames.isEmpty()) {result.add(actualTableNames);
}
}
return result;
}
private Set<String> getActualTableNames(final String dataSourceName, final String logicTableName) {Set<String> result = new HashSet<>(tableUnits.size(), 1);
for (TableUnit each : tableUnits) {result.addAll(each.getActualTableNames(dataSourceName, logicTableName));
}
return result;
}
/**
* Get map relationship between data source and logic tables via data sources' names.
*
* @param dataSourceNames data sources' names
* @return map relationship between data source and logic tables
*/
public Map<String, Set<String>> getDataSourceLogicTablesMap(final Collection<String> dataSourceNames) {Map<String, Set<String>> result = new HashMap<>();
for (String each : dataSourceNames) {Set<String> logicTableNames = getLogicTableNames(each);
if (!logicTableNames.isEmpty()) {result.put(each, logicTableNames);
}
}
return result;
}
private Set<String> getLogicTableNames(final String dataSourceName) {Set<String> result = new HashSet<>(tableUnits.size(), 1);
for (TableUnit each : tableUnits) {if (each.getDataSourceName().equalsIgnoreCase(dataSourceName)) {result.addAll(each.getLogicTableNames(dataSourceName));
}
}
return result;
}
}
- TableUnits 内部是 TableUnit 的集合
TableUnit
incubator-shardingsphere-4.0.0-RC1/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/type/TableUnit.java
@RequiredArgsConstructor
@Getter
@EqualsAndHashCode
@ToString
public final class TableUnit {
private final String dataSourceName;
private final String masterSlaveLogicDataSourceName;
private final List<RoutingTable> routingTables = new LinkedList<>();
public TableUnit(final String dataSourceName) {
this.dataSourceName = dataSourceName;
masterSlaveLogicDataSourceName = dataSourceName;
}
/**
* Get routing table via data source name and actual table name.
*
* @param dataSourceName data source name
* @param actualTableName actual table name
* @return routing table
*/
public Optional<RoutingTable> getRoutingTable(final String dataSourceName, final String actualTableName) {for (RoutingTable each : routingTables) {if (dataSourceName.equalsIgnoreCase(masterSlaveLogicDataSourceName) && each.getActualTableName().equalsIgnoreCase(actualTableName)) {return Optional.of(each);
}
}
return Optional.absent();}
/**
* Get actual tables' names via data source name.
*
* @param dataSourceName data source name
* @param logicTableName logic table name
* @return actual tables' names
*/
public Set<String> getActualTableNames(final String dataSourceName, final String logicTableName) {Set<String> result = new HashSet<>(routingTables.size(), 1);
for (RoutingTable each : routingTables) {if (dataSourceName.equalsIgnoreCase(this.dataSourceName) && each.getLogicTableName().equalsIgnoreCase(logicTableName)) {result.add(each.getActualTableName());
}
}
return result;
}
/**
* Get logic tables' names via data source name.
*
* @param dataSourceName data source name
* @return logic tables' names
*/
public Set<String> getLogicTableNames(final String dataSourceName) {Set<String> result = new HashSet<>(routingTables.size(), 1);
for (RoutingTable each : routingTables) {if (dataSourceName.equalsIgnoreCase(this.dataSourceName)) {result.add(each.getLogicTableName());
}
}
return result;
}
}
- TableUnit 包含了 RoutingTable 的集合
RoutingTable
incubator-shardingsphere-4.0.0-RC1/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/type/RoutingTable.java
@RequiredArgsConstructor
@Getter
@EqualsAndHashCode
@ToString
public final class RoutingTable {
private final String logicTableName;
private final String actualTableName;
}
- RoutingTable 包含了 logicTableName 与 actualTableName
小结
ShardingMasterSlaveRouter 提供了 route 方法,返回 sqlRouteResult,这里修改了 sqlRouteResult 的 routingResult 的 tableUnits 的 TableUnit 集合
doc
- ShardingMasterSlaveRouter