Sharding-jdbc
Sharding-JDBC核心概念。
LogicTable
数据分片的逻辑表,对于水平拆分的数据库(表),同一类表的总称。
例:用户信息表拆分为2张表,分别是t_order_0、t_order_1,他们的逻辑表名为t_order。
ActualTable
在分片的数据库中真实存在的物理表。即上个示例中的t_order_0、t_order_1。
DataNode
数据分片的最小单元。由数据源名称和数据表组成,例:test_msg0.t_order_0。配置时默认各个分片数据库的表结构均相同,直接配置逻辑表和真实表对应关系即可。
ShardingColumn
分片字段。用于将数据库(表)水平拆分的关键字段。SQL中如果无分片字段,将执行全路由,性能较差。Sharding-JDBC支持多分片字段。
ShardingAlgorithm
分片算法。Sharding-JDBC通过分片算法将数据分片,支持通过等号、BETWEEN和IN分片。分片算法目前需要业务方开发者自行实现,可实现的灵活度非常高。未来Sharding-JDBC也将会实现常用分片算法,如range,hash和tag等。
分库分表配置
分表分库配置会涉及如下类:
public static TableRule.TableRuleBuilder builder(String logicTable) {
return new TableRule.TableRuleBuilder(logicTable);
}
方法实现一个tableRule调用内部类;
public TableRule build() {
KeyGenerator keyGenerator = null;
if(null != this.generateKeyColumn && null != this.keyGeneratorClass) {
keyGenerator = KeyGeneratorFactory.createKeyGenerator(this.keyGeneratorClass);
}
return new TableRule(this.logicTable, this.dynamic, this.actualTables, this.dataSourceRule, this.dataSourceNames, this.databaseShardingStrategy, this.tableShardingStrategy, this.generateKeyColumn, keyGenerator);
}
最终初始化TableRule:
大多数业务场景下,我们使用静态分库分表数据单元,即 DataNode。如上文注释处 静态表的分库分表数据单元 处所见,分成两种判断,实质上第一种是将logicTable作为 actualTable,即在库里不进行分表,是第二种的一种特例。
我们来看看 generateDataNodes()方法:
参数说明:
private Collection<String> getDataSourceNames(DataSourceRule dataSourceRule, Collection<String> actualDataSourceNames) {
return (Collection)(null == dataSourceRule?Collections.emptyList():(null != actualDataSourceNames && !actualDataSourceNames.isEmpty()?actualDataSourceNames:dataSourceRule.getDataSourceNames()));
}
public class ModuloDatabaseShardingAlgorithm implements SingleKeyDatabaseShardingAlgorithm<Long>
SingleKeyDatabaseShardingAlgorithm接口的定义如下:
public interface DatabaseShardingAlgorithm extends ShardingAlgorithm {
}
SingleKeyShardingAlgorithm``接口同样继承了ShardingAlgorithm ```
private Collection> doSharding(final Collection<?>> shardingValues, final Collection> availableTargetNames) {
if (shardingAlgorithm instanceof NoneKeyShardingAlgorithm) {
return Collections.singletonList(((NoneKeyShardingAlgorithm) shardingAlgorithm).doSharding(availableTargetNames, shardingValues.iterator().next()));
}
if (shardingAlgorithm instanceof SingleKeyShardingAlgorithm) {
SingleKeyShardingAlgorithm<?> singleKeyShardingAlgorithm = (SingleKeyShardingAlgorithm<?>) shardingAlgorithm;
ShardingValue shardingValue = shardingValues.iterator().next();
switch (shardingValue.getType()) {
case SINGLE:
return Collections.singletonList(singleKeyShardingAlgorithm.doEqualSharding(availableTargetNames, shardingValue));
case LIST:
return singleKeyShardingAlgorithm.doInSharding(availableTargetNames, shardingValue);
case RANGE:
return singleKeyShardingAlgorithm.doBetweenSharding(availableTargetNames, shardingValue);
default:
throw new UnsupportedOperationException(shardingValue.getType().getClass().getName());
}
}
if (shardingAlgorithm instanceof MultipleKeysShardingAlgorithm) {
return ((MultipleKeysShardingAlgorithm) shardingAlgorithm).doSharding(availableTargetNames, shardingValues);
}
throw new UnsupportedOperationException(shardingAlgorithm.getClass().getName());
}
进行debug,当请求接口进行数据插入时,首先调用ModuloDatabaseShardingAlgorithm类中的doEqualSharding进行分库策略的使用。
通过此方法确定数据源dataSource1;