ShardingJdbc 读写分离源码浅析
项目中使用了SJ,但是只用到了读写分离的部分功能。
在看源码中觉得其中的那个轮循的算法写的比较有意思,这里标记一下。
首先通过MasterSlaveDataSourceFactory来创建DataSource:
public MasterSlaveDataSource(final Map<String, DataSource> dataSourceMap, final MasterSlaveRuleConfiguration masterSlaveRuleConfig, final Map<String, Object> configMap, final Properties props) throws SQLException { super(getAllDataSources(dataSourceMap, masterSlaveRuleConfig.getMasterDataSourceName(), masterSlaveRuleConfig.getSlaveDataSourceNames())); if (!configMap.isEmpty()) { ConfigMapContext.getInstance().getMasterSlaveConfig().putAll(configMap); } this.dataSourceMap = dataSourceMap; this.masterSlaveRule = new MasterSlaveRule(masterSlaveRuleConfig); shardingProperties = new ShardingProperties(null == props ? new Properties() : props); }
这里通过将配置的主从DataSourrce信息和主从规则等信息传递进来,其中对DataSource没有什么要求,笔者项目中用的是阿里的Druid,这些都无关紧要。
this.masterSlaveRule = new MasterSlaveRule(masterSlaveRuleConfig);
这里创建了一个主从规则的对象,我们从这里深入:
public MasterSlaveRule(final MasterSlaveRuleConfiguration config) { Preconditions.checkNotNull(config.getName(), "Master-slave rule name cannot be null."); Preconditions.checkNotNull(config.getMasterDataSourceName(), "Master data source name cannot be null."); Preconditions.checkNotNull(config.getSlaveDataSourceNames(), "Slave data source names cannot be null."); Preconditions.checkState(!config.getSlaveDataSourceNames().isEmpty(), "Slave data source names cannot be empty."); name = config.getName(); masterDataSourceName = config.getMasterDataSourceName(); slaveDataSourceNames = config.getSlaveDataSourceNames(); loadBalanceAlgorithm = null == config.getLoadBalanceAlgorithm() ? MasterSlaveLoadBalanceAlgorithmType.getDefaultAlgorithmType().getAlgorithm() : config.getLoadBalanceAlgorithm(); }
这里在最后有一个数据源选择的负载均衡算法设置
public enum MasterSlaveLoadBalanceAlgorithmType { ROUND_ROBIN(new RoundRobinMasterSlaveLoadBalanceAlgorithm()), RANDOM(new RandomMasterSlaveLoadBalanceAlgorithm()); private final MasterSlaveLoadBalanceAlgorithm algorithm; /** * Get default master-slave database load-balance algorithm type. * * @return default master-slave database load-balance algorithm type */ public static MasterSlaveLoadBalanceAlgorithmType getDefaultAlgorithmType() { return ROUND_ROBIN; } }
这里目前只给了两个默认的实现,一个是随机,一个是ROUND_ROBIN。
这里如果用户觉得这个不能满足自己业务场景的需求,可以实现
MasterSlaveLoadBalanceAlgorithmType接口,自定义选择算法
public enum MasterSlaveLoadBalanceAlgorithmType { ROUND_ROBIN(new RoundRobinMasterSlaveLoadBalanceAlgorithm()), RANDOM(new RandomMasterSlaveLoadBalanceAlgorithm()); private final MasterSlaveLoadBalanceAlgorithm algorithm; /** * Get default master-slave database load-balance algorithm type. * * @return default master-slave database load-balance algorithm type */ public static MasterSlaveLoadBalanceAlgorithmType getDefaultAlgorithmType() { return ROUND_ROBIN; } }
下面分别看一下默认提供的两种算法的实现:
- 随机
public final class RandomMasterSlaveLoadBalanceAlgorithm implements MasterSlaveLoadBalanceAlgorithm { @Override public String getDataSource(final String name, final String masterDataSourceName, final List<String> slaveDataSourceNames) { return slaveDataSourceNames.get(new Random().nextInt(slaveDataSourceNames.size())); } }
这里就是Random.nextInt , 没有太多解释的
- ROUND_ROBIN
public final class RoundRobinMasterSlaveLoadBalanceAlgorithm implements MasterSlaveLoadBalanceAlgorithm { private static final ConcurrentHashMap<String, AtomicInteger> COUNT_MAP = new ConcurrentHashMap<>(); @Override public String getDataSource(final String name, final String masterDataSourceName, final List<String> slaveDataSourceNames) { AtomicInteger count = COUNT_MAP.containsKey(name) ? COUNT_MAP.get(name) : new AtomicInteger(0); COUNT_MAP.putIfAbsent(name, count); count.compareAndSet(slaveDataSourceNames.size(), 0); return slaveDataSourceNames.get(count.getAndIncrement() % slaveDataSourceNames.size()); } }
十分的轻量级,很巧妙。

浙公网安备 33010602011771号