聊聊sharding-jdbc的ShardingMasterSlaveRouter

本文主要研究一下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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,029评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,238评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,576评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,214评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,324评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,392评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,416评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,196评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,631评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,919评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,090评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,767评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,410评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,090评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,328评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,952评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,979评论 2 351

推荐阅读更多精彩内容