1、什么时候需要分库分表?
- 数据量大,并发量高,数据库压力较大(这个没什么好说的,到这一步分库分表是很自然的事情)
- 一个系统,多种数据源:前两天接到产品经理一个需求,要给现有的一个非常基础又较为庞大的老爷服务加个功能:要能够给另外一套模拟生产的服务提供完全一样的接口,内部使用完全一样的逻辑,然后要数据隔离,最好还能对原有代码低入侵,接口加个参数判断下就能拿到两种数据。
作为一个程序员,我的宗旨是对于老古董,能不看就不看。所以经过我的琢磨,加上最近刚好在学习分库分表这块的东西,那就分库分表吧。
插件demo地址在 这里
2、如何实现分库分表
2.1、原理
根据请求动态路由到不同的数据库,不同的表。
2.2、实现
2.2.1、配置多数据源
实现自己的MultiDataSource,继承AbstractRoutingDataSource抽象类,实现determineCurrentLookupKey()方法。
public class MultiDataSource extends AbstractRoutingDataSource {
@Nullable
@Override
protected Object determineCurrentLookupKey() {
return MultiDataSourceHolder.getDataSourceKey();
}
}
public class MultiDataSourceHolder {
private static final ThreadLocal<String> dataSourceHolder = new ThreadLocal<>();
private static final ThreadLocal<String> tableIndexHolder = new ThreadLocal<>();
/**
* 保存数据源的key
* @param dsKey
*/
public static void setDataSourceHolder(String dsKey){
dataSourceHolder.set(dsKey);
}
/**
* 从threadLocal中取出key
* @return
*/
public static String getDataSourceKey(){
return dataSourceHolder.get();
}
/**
* 清除key
*/
public static void clearDataSourceKey(){
dataSourceHolder.remove();
}
/**
* 保存表索引
* @param tableIndex
*/
public static void setTableIndexHolder(String tableIndex){
tableIndexHolder.set(tableIndex);
}
/**
* 从threadLocal中取出索引
* @return
*/
public static String getTableIndex(){
return tableIndexHolder.get();
}
/**
* 清除表索引
*/
public static void clearTableIndex(){
tableIndexHolder.remove();
}
}
2.2.2、配置mybatis
- 配置mybatis的SqlSessionFactory,指定数据源为自己配置的多数据源
- 配置SqlSessionTemplate,指定数据SqlSessionFactory的工程
@EnableConfigurationProperties({
DsRoutingSetProperties.class, DruidProperties.class})
@Configuration
public class DataSourceConfig {
@Autowired
private DsRoutingSetProperties dsRoutingSetProperties;
@Autowired
private DruidProperties druidProperties;
@Bean
@ConfigurationProperties(prefix = "spring.datasource.druid00")
public DataSource dataSource00(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUsername(druidProperties.getDruid00username());
dataSource.setPassword(druidProperties.getDruid00password());
dataSource.setUrl(druidProperties.getDruid00jdbcUrl());
dataSource.setDriverClassName(druidProperties.getDruid00driverClass());
return dataSource;
}
@Bean
@ConfigurationProperties(prefix = "spring.datasource.druid01")
public DataSource dataSource01(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.