本文主要研究一下sharding-jdbc的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; } }
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); } }
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(); } }
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; } }
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; } }
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; }
ShardingMasterSlaveRouter提供了route方法,返回sqlRouteResult,这里修改了sqlRouteResult的routingResult的tableUnits的TableUnit集合