##简单实用
概述
最近公司要某业务要实现分表分库,根据目前公司的技术栈进行了选型,选择 shardingsphere,接下来记录下这次集成的过程,希望对需要做这块业务的开发人员有所帮助。
依赖的框架以及版本
实现步骤
1,先添加 shardingsphere 依赖,shardingsphere 的 4.x 版本较之前变化蛮大的。
<dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-boot-starter</artifactId> <version>4.1.1</version></dependency><!-- for spring namespace --><dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-namespace</artifactId> <version>4.1.1</version></dependency>
复制代码
2,添加依赖后,接下来新建 DataSourceConfiguration 这个配置类去将这个 shardingsphere 的数据源交给 dynamic-datasource 去维护。
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;import com.baomidou.dynamic.datasource.provider.AbstractDataSourceProvider;import com.baomidou.dynamic.datasource.provider.DynamicDataSourceProvider;import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;import lombok.extern.slf4j.Slf4j;import org.apache.tomcat.util.buf.StringUtils;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.EnvironmentAware;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.DependsOn;import org.springframework.context.annotation.Primary;import org.springframework.core.env.Environment;import javax.annotation.Resource;import javax.sql.DataSource;import java.util.HashMap;import java.util.Map;
@Configuration@DependsOn("shardingDataSource")@Slf4jpublic class DataSourceConfiguration implements EnvironmentAware {
private final DynamicDataSourceProperties properties;
public DataSourceConfiguration(DynamicDataSourceProperties properties) { this.properties = properties; }
@Resource(name = "shardingDataSource") private DataSource shardingDataSource;
@Value("${spring.shardingsphere.datasource.names:}") private String shardingDataSourceName;
@Bean public DynamicDataSourceProvider dynamicDataSourceProvider() { return new AbstractDataSourceProvider() {
@Override public Map<String, DataSource> loadDataSources() { Map<String, DataSource> dataSourceMap = new HashMap<>(); if (org.springframework.util.StringUtils.isEmpty(shardingDataSourceName)){ return dataSourceMap; } dataSourceMap.put(shardingDataSourceName, shardingDataSource); return dataSourceMap; } }; }
@Primary @Bean public DataSource dataSource() { DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource(); dataSource.setPrimary(properties.getPrimary()); dataSource.setStrict(properties.getStrict()); dataSource.setStrategy(properties.getStrategy()); dataSource.setP6spy(properties.getP6spy()); dataSource.setSeata(properties.getSeata()); return dataSource; }
@Override public void setEnvironment(Environment environment) { log.error(StringUtils.join(environment.getActiveProfiles())); }}
复制代码
3,再接下来,在配置文件中添加如下配置,其中可以看到我们使用 primary 为主数据源,默认的数据库操作都会找这个数据源。其他的分库分表操作走 sharding0 等等数据源即可。之所以这样配置主要是因为老项目介入发表分库业务,不希望影响太大。
#默认数据源spring.datasource.dynamic.primary=primary
#mysql1数据源配置spring.datasource.dynamic.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driverspring.datasource.dynamic.datasource.primary.url=jdbc:mysql://xxxxx:3306/sample?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&useSSL=falsespring.datasource.dynamic.datasource.primary.username=xxxxxspring.datasource.dynamic.datasource.primary.password=xxxxx
# 数据源 sharding0spring.shardingsphere.datasource.names=sharding0
# 分库分表数据库spring.shardingsphere.datasource.sharding0.type=com.alibaba.druid.pool.DruidDataSourcespring.shardingsphere.datasource.sharding0.driver-class-name=com.mysql.cj.jdbc.Driverspring.shardingsphere.datasource.sharding0.url=jdbc:mysql://xxxxx:3306/sample?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTCspring.shardingsphere.datasource.sharding0.username=xxxxxspring.shardingsphere.datasource.sharding0.password=xxxxxspring.shardingsphere.sharding.tables.book.actual-data-nodes=sharding0.book,sharding0.book_historyspring.shardingsphere.sharding.tables.book.table-strategy.standard.sharding-column=count1spring.shardingsphere.sharding.tables.book.table-strategy.standard.precise-algorithm-class-name=com.diligence.shardingsphere.algoritm.MyPreciseShardingAlgorithmspring.shardingsphere.sharding.binding-tables=book
# 打印执行的数据库以及语句spring.shardingsphere.props..sql.show=truespring.main.allow-bean-definition-overriding=truemybatis-plus.mapper-locations=classpath*:mapper/**/*Mapper.xml
复制代码
4,增加 MyPreciseShardingAlgorithm 分片策略实现分表逻辑。
public class MyPreciseShardingAlgorithm implements PreciseShardingAlgorithm<Integer> {
@Override public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Integer> shardingValue) { Optional<Integer> shardingValueOpl = Optional.ofNullable(shardingValue.getValue()); if (shardingValueOpl.get()==1) return "book" ; return "book_history"; }}
复制代码
5,增加 ShardDS 方便数据源统一维护。
@Target({ElementType.TYPE, ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@Documented@DS(value = "sharding0")public @interface ShardDS {}
复制代码
6,至此,集成完毕。使用的时候只需要在相应的需要分表分库的数据库操作的地方使用 ShardDS 注解做数据源切换。例如:
@ShardDS@Overridepublic List<SampleResponse> getBookList() { return sampleMapper.selectSampleList("88888");}
复制代码
异常报错
集成过程中遇到了如下异常:
java.lang.IllegalArgumentException: Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required
解决方法:添加上面的 DataSourceConfiguration 类,注入数据源
有时候会遇到,shardingDataSource 为空
解决办法:在 DataSourceConfiguration 类上添加 @DependsOn("shardingDataSource")
注意事项
简单测试了 shardingsphere,使用上需要注意的地方:
通过子查询实现业务查询当前并不能支持;
不要使用 update 去修改分片键,这里可以用 delete 后 insert 代替。
参考
例子代码
shardingsphere对哪些SQL的支持
评论