分库分表之ShardingSphere读写分离源码分析

1. 问题

读写分离如何执行

2. 源码

ShardingMasterSlaveRouter为核心入口
public SQLRouteResult route(SQLRouteResult sqlRouteResult) {
    Iterator var2 = this.masterSlaveRules.iterator();

    while(var2.hasNext()) {
        MasterSlaveRule each = (MasterSlaveRule)var2.next();
        // 开始路由
        this.route(each, sqlRouteResult);
    }

    return sqlRouteResult;
}
private void route(MasterSlaveRule masterSlaveRule, SQLRouteResult sqlRouteResult) {
    Collection<RoutingUnit> toBeRemoved = new LinkedList();
    Collection<RoutingUnit> toBeAdded = new LinkedList();
    Iterator var5 = sqlRouteResult.getRoutingResult().getRoutingUnits().iterator();

    while(var5.hasNext()) {
        RoutingUnit each = (RoutingUnit)var5.next();
        if (masterSlaveRule.getName().equalsIgnoreCase(each.getDataSourceName())) {
            toBeRemoved.add(each);
            String actualDataSourceName;
            // 判断是否走主库
            if (this.isMasterRoute(sqlRouteResult.getSqlStatementContext().getSqlStatement())) {
                MasterVisitedManager.setMasterVisited();
                actualDataSourceName = masterSlaveRule.getMasterDataSourceName();
            } else {
            //  从库如果有多个,默认是轮询,也可以选择随机访问策略
                actualDataSourceName = masterSlaveRule.getLoadBalanceAlgorithm().getDataSource(masterSlaveRule.getName(), masterSlaveRule.getMasterDataSourceName(), new ArrayList(masterSlaveRule.getSlaveDataSourceNames()));
            }

            toBeAdded.add(this.createNewRoutingUnit(actualDataSourceName, each));
        }
    }

    sqlRouteResult.getRoutingResult().getRoutingUnits().removeAll(toBeRemoved);
    sqlRouteResult.getRoutingResult().getRoutingUnits().addAll(toBeAdded);
} 

判断是否走主库,包括hint和非查询操作等 

private boolean isMasterRoute(SQLStatement sqlStatement) {
    return this.containsLockSegment(sqlStatement) || !(sqlStatement instanceof SelectStatement) || MasterVisitedManager.isMasterVisited() || HintManager.isMasterRouteOnly();
}

// HintManager可以设置强制走主库,或者非查询操作走主库

RoundRobinMasterSlaveLoadBalanceAlgorithm类执行轮询查询从库策略
// 轮询访问从库
@Override
public String getDataSource(final String name, final String masterDataSourceName, final List<String> slaveDataSourceNames) {
    AtomicInteger count = COUNTS.containsKey(name) ? COUNTS.get(name) : new AtomicInteger(0);
    COUNTS.putIfAbsent(name, count);
    count.compareAndSet(slaveDataSourceNames.size(), 0);
    // 计数器来实现轮询
    return slaveDataSourceNames.get(Math.abs(count.getAndIncrement()) % slaveDataSourceNames.size());
}
发布了210 篇原创文章 · 获赞 105 · 访问量 18万+

猜你喜欢

转载自blog.csdn.net/u010627840/article/details/103684913