概要: ShardingSphere是一套開源的分佈式數據庫中間件解決方案組成的生態圈,它由Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar(計劃中)這3款相互獨立的產品組成。 他們均提供標準化的數據分片、分佈式事務和數據庫治理功能,可適用於如Java同構、異構語言、雲原生等各種多樣化的應用場景。
官網地址:https://shardingsphere.apache.org/
一、相關依賴
<dependency>
<groupId>io.shardingsphere</groupId>
<artifactId>sharding-core</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>io.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-namespace</artifactId>
<version>3.1.0</version>
</dependency>
二、Nacos數據源配置
spring:
profiles:
active: dev
sharding:
datasource:
db0:
driverClassName: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://127.0.0.1:3306/demo0
username: root
password: 123456
db1:
driverClassName: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://127.0.0.1:3306/demo1
username: root
password: 123456
三、項目配置
- bootstrap-dev.properties
spring:
application:
name: demo
cloud:
nacos:
server-addr: 127.0.0.1:8848
config:
namespace: 9c6b8156-d045-463d-8fe6-4658ce78d0cc
file-extension: yml
- 數據源及路由規則配置
package com.example.demo.config;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import io.shardingsphere.api.config.rule.ShardingRuleConfiguration;
import io.shardingsphere.api.config.rule.TableRuleConfiguration;
import io.shardingsphere.api.config.strategy.InlineShardingStrategyConfiguration;
import io.shardingsphere.shardingjdbc.api.ShardingDataSourceFactory;
import org.apache.ibatis.plugin.Interceptor;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
@Configuration
public class SqlSessionConfig {
private Logger logger = LoggerFactory.getLogger(SqlSessionConfig.class);
@Bean("db0")
@ConfigurationProperties(prefix = "sharding.datasource.db0")
public DataSource getDataSource0() {
return DataSourceBuilder.create().build();
}
@Bean("db1")
@ConfigurationProperties(prefix = "sharding.datasource.db1")
public DataSource getDataSource1() {
return DataSourceBuilder.create().build();
}
@Bean("datasource")
public DataSource getDataSource1(@Qualifier("db0") DataSource db0, @Qualifier("db1") DataSource db1) throws SQLException {
Map<String, DataSource> dataSourceMap = new HashMap<>();
dataSourceMap.put("db0", db0);
dataSourceMap.put("db1", db1);
TableRuleConfiguration tableRuleConfig = new TableRuleConfiguration();
tableRuleConfig.setLogicTable("user");
tableRuleConfig.setActualDataNodes("db${0..1}.user${0..1}");
// 配置分庫 + 分表策略
tableRuleConfig.setDatabaseShardingStrategyConfig(new InlineShardingStrategyConfiguration("id", "db${id % 2}"));
tableRuleConfig.setTableShardingStrategyConfig(new InlineShardingStrategyConfiguration("id", "user${id % 2}"));
// 配置分片規則
ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
shardingRuleConfig.getTableRuleConfigs().add(tableRuleConfig);
// 獲取數據源對象
return ShardingDataSourceFactory.createDataSource(dataSourceMap, shardingRuleConfig, new HashMap<>(), new Properties());
}
@Bean("mySqlSessionFactoryBean")
public MybatisSqlSessionFactoryBean createSqlSessionFactory(@Qualifier("datasource") DataSource dataSource,
@Qualifier("paginationInterceptor") PaginationInterceptor paginationInterceptor) {
// MybatisSqlSessionFactory
MybatisSqlSessionFactoryBean sqlSessionFactoryBean = null;
try {
// 實例SessionFactory
sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
// 配置數據源
sqlSessionFactoryBean.setDataSource(dataSource);
// 設置 MyBatis-Plus 分頁插件
Interceptor [] plugins = {paginationInterceptor};
sqlSessionFactoryBean.setPlugins(plugins);
// 加載MyBatis配置文件
PathMatchingResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
sqlSessionFactoryBean.setMapperLocations(resourcePatternResolver.getResources("classpath*:mapper/*.xml"));
} catch (Exception e) {
logger.error("創建SqlSession連接工廠錯誤:{}", e.getMessage());
}
return sqlSessionFactoryBean;
}
@Bean
public MapperScannerConfigurer myGetMapperScannerConfigurer() {
MapperScannerConfigurer myMapperScannerConfigurer = new MapperScannerConfigurer();
myMapperScannerConfigurer.setBasePackage("com.example.demo.mapper");
myMapperScannerConfigurer.setSqlSessionFactoryBeanName("mySqlSessionFactoryBean");
return myMapperScannerConfigurer;
}
}
四、驗證
2020-05-09 17:34:11.730 INFO 2176 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$9444c32f] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.2.6.RELEASE)
2020-05-09 17:34:11.969 INFO 2176 --- [ main] c.a.c.n.c.NacosPropertySourceBuilder : Loading nacos data, dataId: 'demo', group: 'DEFAULT_GROUP', data: spring:
profiles:
active: dev
sharding:
datasource:
db0:
driverClassName: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://106.13.181.6:3306/demo0
username: root
password: 123456
db1:
driverClassName: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://106.13.181.6:3306/demo1
username: root
password: 123456
2020-05-09 17:34:11.977 WARN 2176 --- [ main] c.a.c.n.c.NacosPropertySourceBuilder : Ignore the empty nacos configuration and get it based on dataId[demo.yml] & group[DEFAULT_GROUP]
2020-05-09 17:34:11.982 WARN 2176 --- [ main] c.a.c.n.c.NacosPropertySourceBuilder : Ignore the empty nacos configuration and get it based on dataId[demo-dev.yml] & group[DEFAULT_GROUP]
2020-05-09 17:34:11.982 INFO 2176 --- [ main] b.c.PropertySourceBootstrapConfiguration : Located property source: CompositePropertySource {name='NACOS', propertySources=[NacosPropertySource {name='demo-dev.yml'}, NacosPropertySource {name='demo.yml'}, NacosPropertySource {name='demo'}]}
2020-05-09 17:34:11.986 INFO 2176 --- [ main] com.example.demo.DemoApplication : The following profiles are active: dev
2020-05-09 17:34:12.431 WARN 2176 --- [ main] o.m.s.mapper.ClassPathMapperScanner : Skipping MapperFactoryBean with name 'userMapper' and 'com.example.demo.mapper.UserMapper' mapperInterface. Bean already defined with the same name!
2020-05-09 17:34:12.432 WARN 2176 --- [ main] o.m.s.mapper.ClassPathMapperScanner : No MyBatis mapper was found in '[com.example.demo.mapper]' package. Please check your configuration.
2020-05-09 17:34:12.433 INFO 2176 --- [ main] o.s.c.a.ConfigurationClassPostProcessor : Cannot enhance @Configuration bean definition 'sqlSessionConfig' since its singleton instance has been created too early. The typical cause is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor return type: Consider declaring such methods as 'static'.
2020-05-09 17:34:12.469 INFO 2176 --- [ main] o.s.cloud.context.scope.GenericScope : BeanFactory id=68ee7a81-358c-3325-ab3b-eed7cbbbb28e
2020-05-09 17:34:12.638 INFO 2176 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$9444c32f] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-05-09 17:34:12.894 INFO 2176 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2020-05-09 17:34:12.902 INFO 2176 --- [ main] o.a.coyote.http11.Http11NioProtocol : Initializing ProtocolHandler ["http-nio-8080"]
2020-05-09 17:34:12.902 INFO 2176 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2020-05-09 17:34:12.903 INFO 2176 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.33]
2020-05-09 17:34:13.031 INFO 2176 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2020-05-09 17:34:13.031 INFO 2176 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1034 ms
2020-05-09 17:34:13.332 INFO 2176 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2020-05-09 17:34:14.086 INFO 2176 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2020-05-09 17:34:14.095 INFO 2176 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-2 - Starting...
2020-05-09 17:34:14.794 INFO 2176 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-2 - Start completed.
_ _ |_ _ _|_. ___ _ | _
| | |\/|_)(_| | |_\ |_)||_|_\
/ |
3.3.1
2020-05-09 17:34:15.464 WARN 2176 --- [ main] c.n.c.sources.URLConfigurationSource : No URLs will be polled as dynamic configuration sources.
2020-05-09 17:34:15.464 INFO 2176 --- [ main] c.n.c.sources.URLConfigurationSource : To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath.
2020-05-09 17:34:15.467 WARN 2176 --- [ main] c.n.c.sources.URLConfigurationSource : No URLs will be polled as dynamic configuration sources.
2020-05-09 17:34:15.467 INFO 2176 --- [ main] c.n.c.sources.URLConfigurationSource : To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath.
2020-05-09 17:34:15.626 INFO 2176 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2020-05-09 17:34:15.869 INFO 2176 --- [ main] o.s.s.c.ThreadPoolTaskScheduler : Initializing ExecutorService
2020-05-09 17:34:16.122 INFO 2176 --- [ main] o.a.coyote.http11.Http11NioProtocol : Starting ProtocolHandler ["http-nio-8080"]
2020-05-09 17:34:16.140 INFO 2176 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2020-05-09 17:34:16.198 INFO 2176 --- [ main] c.a.c.n.registry.NacosServiceRegistry : nacos registry, DEFAULT_GROUP demo 10.118.37.75:8080 register finished
2020-05-09 17:34:16.259 INFO 2176 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 5.486 seconds (JVM running for 6.559)
2020-05-09 17:34:23.596 INFO 2176 --- [nio-8080-exec-2] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2020-05-09 17:34:23.596 INFO 2176 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2020-05-09 17:34:23.602 INFO 2176 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Completed initialization in 6 ms
2020-05-09 17:34:23.682 INFO 2176 --- [nio-8080-exec-2] com.example.demo.config.LogAspect :
請求信息:
【請求地址】:/demo/create
【請求頭】:content-type = application/json, user-agent = PostmanRuntime/7.24.0, accept = */*, postman-token = 086e76ac-a9fa-4437-884a-dfbe5ce61b9e, host = localhost:8080, accept-encoding = gzip, deflate, br, connection = keep-alive, content-length = 61
【請求方法】:String com.example.demo.controller.UserController.create(UserDTO)
【請求參數】:[UserDTO(id=123456, name=zhangsan, phone=17751033130, sex=1)]
2020-05-09 17:34:23.730 DEBUG 2176 --- [nio-8080-exec-2] c.example.demo.mapper.UserMapper.insert : ==> Preparing: INSERT INTO user ( id, name, sex, phone, create_time, enable, version ) VALUES ( ?, ?, ?, ?, ?, ?, ? )
2020-05-09 17:34:23.744 DEBUG 2176 --- [nio-8080-exec-2] c.example.demo.mapper.UserMapper.insert : ==> Parameters: 123456(Long), zhangsan(String), MAN(String), 17751033130(String), 2020-05-09T17:34:23.686(LocalDateTime), true(Boolean), 1(Long)
2020-05-09 17:34:24.053 DEBUG 2176 --- [nio-8080-exec-2] c.example.demo.mapper.UserMapper.insert : <== Updates: 1
2020-05-09 17:34:24.056 INFO 2176 --- [nio-8080-exec-2] com.example.demo.config.LogAspect :
執行結果:
【響應結果】:"ok"
【執行耗時】:374毫秒
2020-05-09 17:38:15.807 INFO 2176 --- [nio-8080-exec-5] com.example.demo.config.LogAspect :
請求信息:
【請求地址】:/demo/create
【請求頭】:content-type = application/json, user-agent = PostmanRuntime/7.24.0, accept = */*, postman-token = 216c99c3-f6b4-4e9d-9b9a-f3e3f7991fd5, host = localhost:8080, accept-encoding = gzip, deflate, br, connection = keep-alive, content-length = 61
【請求方法】:String com.example.demo.controller.UserController.create(UserDTO)
【請求參數】:[UserDTO(id=123457, name=zhangsan, phone=17751033130, sex=1)]
2020-05-09 17:38:15.809 DEBUG 2176 --- [nio-8080-exec-5] c.example.demo.mapper.UserMapper.insert : ==> Preparing: INSERT INTO user ( id, name, sex, phone, create_time, enable, version ) VALUES ( ?, ?, ?, ?, ?, ?, ? )
2020-05-09 17:38:15.809 DEBUG 2176 --- [nio-8080-exec-5] c.example.demo.mapper.UserMapper.insert : ==> Parameters: 123457(Long), zhangsan(String), MAN(String), 17751033130(String), 2020-05-09T17:38:15.807(LocalDateTime), true(Boolean), 1(Long)
2020-05-09 17:38:16.012 DEBUG 2176 --- [nio-8080-exec-5] c.example.demo.mapper.UserMapper.insert : <== Updates: 1
2020-05-09 17:38:16.012 INFO 2176 --- [nio-8080-exec-5] com.example.demo.config.LogAspect :
執行結果:
【響應結果】:"ok"
【執行耗時】:204毫秒
Disconnected from the target VM, address: '127.0.0.1:61430', transport: 'socket'