1. sharding簡(jiǎn)介
ShardingSphere是一套開(kāi)源的分布式數(shù)據(jù)庫(kù)中間件解決方案組成的生態(tài)圈,目前已在阿帕奇孵化成功,它由Sharding-JDBC恩脂、Sharding-Proxy和Sharding-Sidecar(計(jì)劃中)這3款相互獨(dú)立的產(chǎn)品組成缸剪,這里主要介紹shardingjdbc,文檔地址 https://shardingsphere.apache.org/document/current/cn/overview/
2. 使用
1.引入maven包
這里不適用start包,而直接使用原包,這里還需要排除sharding的mysql連接器,使用自己的連接器
<!-- https://mvnrepository.com/artifact/io.shardingsphere/sharding-jdbc-core -->
<dependency>
<groupId>io.shardingsphere</groupId>
<artifactId>sharding-jdbc-core</artifactId>
<version>3.1.0</version>
<exclusions>
<exclusion>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</exclusion>
</exclusions>
</dependency>
2.配置
sharding和動(dòng)態(tài)數(shù)據(jù)源整合一起,因?yàn)閟harding會(huì)全局解析所有sql,在某些情況下mybatis能解析的sql語(yǔ)句sharding是沒(méi)辦法解析的,會(huì)導(dǎo)致以前的業(yè)務(wù)sql出現(xiàn)問(wèn)題,所以我們通過(guò)動(dòng)態(tài)數(shù)據(jù)源和注解的形式標(biāo)注哪些sql需要使用sharding的數(shù)據(jù)源,靈活配置
DynamicDataSource
/**
* 動(dòng)態(tài)數(shù)據(jù)源
* Created by tyf on 2019/9/25 0025
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
//用來(lái)保存數(shù)據(jù)源與獲取數(shù)據(jù)源
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
public DynamicDataSource(DataSource defaultTargetDataSource, Map<String, DataSource> targetDataSources) {
super.setDefaultTargetDataSource(defaultTargetDataSource);
super.setTargetDataSources(new HashMap<>(targetDataSources));
super.afterPropertiesSet();
}
public static void setDataSource(String dataSource) {
contextHolder.set(dataSource);
}
public static String getDataSource() {
return contextHolder.get();
}
public static void clearDataSource() {
contextHolder.remove();
}
@Override
protected Object determineCurrentLookupKey() {
return getDataSource();
}
}
ShardingDataSourceAspect 動(dòng)態(tài)數(shù)據(jù)源aop切面,使用springboot的方式
/**
* 動(dòng)態(tài)數(shù)據(jù)源aop切面
* Created by tyf on 2019/9/25 0025
*/
@Aspect
public class ShardingDataSourceAspect {
@Around(ExecutionConstant.CONTROLLER + "||" + ExecutionConstant.SERVICE)
public Object around(ProceedingJoinPoint point) throws Throwable {
// 獲取方法名
String methodName = point.getSignature().getName();
// 反射獲取目標(biāo)類(lèi)
Class<?> targetClass = point.getTarget().getClass();
// 拿到方法對(duì)應(yīng)的參數(shù)類(lèi)型
Class<?>[] parameterTypes = ((MethodSignature) point.getSignature()).getParameterTypes();
// 根據(jù)類(lèi)、方法东亦、參數(shù)類(lèi)型(重載)獲取到方法的具體信息
Method method = targetClass.getMethod(methodName, parameterTypes);
final ShardingDataSource methodAnnotation = AnnotationUtils.findAnnotation(method, ShardingDataSource.class);
final ShardingDataSource classAnnotation = AnnotationUtils.findAnnotation(targetClass, ShardingDataSource.class);
//當(dāng)類(lèi)和方法上都沒(méi)注解的時(shí)候,跳過(guò)
if (methodAnnotation == null && classAnnotation == null) {
return point.proceed();
}
DynamicDataSource.setDataSource(DataSourceNames.SHARDING);
try {
return point.proceed();
} finally {
DynamicDataSource.clearDataSource();
}
}
}
ShardingDataSource,注解
/**
* Created by tyf on 2019/9/25 0025
*/
@Target({ ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ShardingDataSource {
}
DataSourceNames常量
/**
* Created by tyf on 2019/9/25 0025
*/
public interface DataSourceNames {
String DEFAULT = "default";
String SHARDING = "sharding";
}
ShardingConfiguration,sharding配置類(lèi),將配置抽象在基礎(chǔ)包中,只有當(dāng)業(yè)務(wù)項(xiàng)目有ShardingRuleConfiguration類(lèi)之后才會(huì)加載sharding配置類(lèi)
@Configuration
@DependsOn("springTools")
@ConditionalOnBean({ShardingRuleConfiguration.class})
public class ShardingConfiguration {
/**
* 代理切面類(lèi)
*
* @return
*/
@Bean
public ShardingDataSourceAspect shardingDataSourceAspect() {
return new ShardingDataSourceAspect();
}
/**
* 多數(shù)據(jù)源,默認(rèn)為springboot數(shù)據(jù)源,使用{@link ShardingDataSource} 標(biāo)記為sharding數(shù)據(jù)源
*
* @param dataSourceProperties
* @param shardingRuleConfiguration
* @return
* @throws SQLException
*/
@Bean
@Primary
public DynamicDataSource dataSource(DataSourceProperties dataSourceProperties, ShardingRuleConfiguration shardingRuleConfiguration) throws SQLException {
//初始化springboot數(shù)據(jù)源
final DataSource dataSource = dataSourceProperties.initializeDataSourceBuilder().build();
//設(shè)置動(dòng)態(tài)數(shù)據(jù)源
Map<String, DataSource> targetDataSources = new HashMap<>();
targetDataSources.put(DataSourceNames.DEFAULT, dataSource);
targetDataSources.put(DataSourceNames.SHARDING, getShardingDataSource(dataSource, shardingRuleConfiguration));
return new DynamicDataSource(dataSource, targetDataSources);
}
private DataSource getShardingDataSource(DataSource dataSource, ShardingRuleConfiguration shardingRuleConfiguration) throws SQLException {
final Properties properties = new Properties();
// 獲取數(shù)據(jù)源對(duì)象
final DataSource shardingDatasource = ShardingDataSourceFactory.createDataSource(ImmutableMap.of("ds0", dataSource),
shardingRuleConfiguration, new ConcurrentHashMap(), properties);
return shardingDatasource;
}
}
在業(yè)務(wù)項(xiàng)目中,你只需要配置ShardingRuleConfiguration即可開(kāi)箱使用sharding了,例如
/**
* sharding分片規(guī)則
*
* @return
*/
@Bean
@Primary
public ShardingRuleConfiguration shardingRuleConfiguration() {
final ShardingRuleConfiguration shardingRuleConfiguration = new ShardingRuleConfiguration();
TableRuleConfiguration sappPaperRankingTableRuleConfig = new TableRuleConfiguration();
sappPaperRankingTableRuleConfig.setLogicTable("sapp_paper_ranking");
//選需要分片的對(duì)應(yīng)的庫(kù)和表
sappPaperRankingTableRuleConfig.setActualDataNodes("ds0.sapp_paper_ranking_0${1..9},ds0.sapp_paper_ranking_${10..31}");
// 配置分庫(kù) + 分表策略
sappPaperRankingTableRuleConfig.setDatabaseShardingStrategyConfig(new NoneShardingStrategyConfiguration());
sappPaperRankingTableRuleConfig.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration(
"create_date", new SappPaperRankingPreciseShardingAlgorithm()));
// 配置分片規(guī)則
shardingRuleConfiguration.getTableRuleConfigs().add(sappPaperRankingTableRuleConfig);
return shardingRuleConfiguration;
}
/**
* 精確分片算法,=與IN進(jìn)行分片
*/
public class SappPaperRankingPreciseShardingAlgorithm implements PreciseShardingAlgorithm<Integer> {
@Override
public String doSharding(Collection<String> tableNames/*表名*/, PreciseShardingValue<Integer> shardingValue /*分片鍵*/) {
final Integer uid = shardingValue.getValue();
/*省略*/
throw new UnsupportedOperationException();
}
}