sharding-jdbc分表
文章例子为按月份分表,将表按月份分为(表_1,表_2…表_12)
ShardingSphere
pom文件导包
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.5</version>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.1.1</version>
</dependency>
yml配置
spring:
shardingsphere:
datasource: # 数据源
master:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.jdbc.Driver
username: ## 用户名称
password: ## 密码
jdbcUrl: jdbc:mysql://ip:host/数据库名?useUnicode=true&autoReconnect=true&characterEncoding=UTF-8&useSSL=true&zeroDateTimeBehavior=convertToNull
names: master
props:
sql.show: true #是否开启SQL显示,默认值: false
max.connections.size.per.query: 8 # 每个查询可以打开的最大连接数量,默认为1,此处可加快项目启动时shardingsphere加载数据库表元数据的速度
sharding:
tables:
${表前缀}: # 如 t_a_1~t_a_12写t_a
actual-data-nodes: master.表前缀_$->{1..12} #表分布情况 {数据源分支.表名}
table-strategy:
standard: # 数据库表分片策略
shardingColumn: insert_time ##按该字段分片
preciseAlgorithmClassName: **.MonthPreciseShardingAlgorithm ##对应类全路径
rangeAlgorithmClassName: **.MonthRangeShardingAlgorithm ##对应类全路径
sharding数据库配置
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
/**
* 数据库配置
*
*/
@Configuration
@MapperScan(basePackages = "分表dao类所在包", sqlSessionTemplateRef = "shardingSqlSessionTemplate")
public class ShardingDataSourceConfig {
@Bean(name = "shardingSqlSessionFactory")
public SqlSessionFactory shardingSqlSessionFactory(@Qualifier("shardingDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/sharding/*.xml"));
return bean.getObject();
}
@Bean(name = "shardingTransactionManager")
public DataSourceTransactionManager shardingTransactionManager(@Qualifier("shardingDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "shardingSqlSessionTemplate")
public SqlSessionTemplate shardingSqlSessionTemplate(@Qualifier("shardingSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
分片策略
MonthPreciseShardingAlgorithm.java
import cn.hutool.core.date.DateUtil
import org.apache.commons.lang3.StringUtils;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
import java.util.Collection;
/**
* 表精确分片算法
* in或=
* 按时间月份分片
* 使用String类型进行分片,则对于分片字段类型应为String
*
*/
public class MonthPreciseShardingAlgorithm implements PreciseShardingAlgorithm<String> {
@Override
public String doSharding(Collection<String> collection, PreciseShardingValue<String> preciseShardingValue) {
// 逻辑表名
String logicTableName = preciseShardingValue.getLogicTableName();
// 分片值
String value = preciseShardingValue.getValue();
if (StringUtils.isBlank(value)) {
throw new BusinessException("分片值异常");
}
int mm = DateUtil.month(DateUtil.parse(value)) + 1;
return logicTableName + "_" + mm;
}
}
MonthRangeShardingAlgorithm.java
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.google.common.collect.Range;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingValue;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
/**
* 表范围分片
* <p>
* 按月份分片
*
*/
public class MonthRangeShardingAlgorithm implements RangeShardingAlgorithm<String> {
@Override
public Collection<String> doSharding(Collection<String> collection, RangeShardingValue<String> rangeShardingValue) {
String logicTableName = rangeShardingValue.getLogicTableName();
Range<String> valueRange = rangeShardingValue.getValueRange();
try {
String startDate = valueRange.lowerEndpoint();
String endDate = valueRange.upperEndpoint();
return getMonthTables(startDate, endDate, logicTableName);
} catch (Exception e) {
e.printStackTrace();
return collection;
}
}
/**
* 获取月表
*
* @param startDate 起始时间
* @param endDate 结束时间
* @param logicTableName 逻辑表名
* @return 结果表名列表
*/
public Set<String> getMonthTables(String startDate, String endDate, String logicTableName) {
DateTime startDateTime = DateUtil.parse(startDate);
DateTime endDateTime = DateUtil.parse(endDate);
Calendar start = Calendar.getInstance();
Calendar end = Calendar.getInstance();
start.setTime(startDateTime);
end.setTime(endDateTime);
Set<String> result = new HashSet<>();
// 添加起始月和结束月
result.add(logicTableName + "_" + (start.get(Calendar.MONTH) + 1));
result.add(logicTableName + "_" + (end.get(Calendar.MONTH) + 1));
while (start.before(end)) {
result.add(logicTableName + "_" + (start.get(Calendar.MONTH) + 1));
start.add(Calendar.MONTH, 1);
}
return result;
}
}