pom文件配置
xml
<!-- Mybatis Plus的依赖,包括Mybatis和Mybatis Plus的核心库 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.2</version>
</dependency>
<!-- ShardingSphere的依赖 -->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-core</artifactId>
<version>5.0.0-alpha</version>
</dependency>
<!-- MySQL数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.23</version>
</dependency>
接着,我们需要在application.yml中进行相关配置。
ShardingSphere配置
yaml
spring:
# 配置数据源
shardingsphere:
datasource:
# 配置主库
master:
url: jdbc:mysql://127.0.0.1:3306/test?useSSL=false&serverTimezone=UTC
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
# 配置从库1
slave0:
url: jdbc:mysql://127.0.0.1:3307/test?useSSL=false&serverTimezone=UTC
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
# 配置从库2
slave1:
url: jdbc:mysql://127.0.0.1:3308/test?useSSL=false&serverTimezone=UTC
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
# 配置读写分离规则
sharding:
default-data-source: master # 默认使用主库
master-slave-rules:
# 配置读写分离规则,每个库都是一主多从
ms0:
master-data-source-name: master
slave-data-source-names:
- slave0
- slave1
# 配置负载均衡算法,这里设置轮询策略
load-balance-algorithm-type: round_robin
对应java代码
我们在MybatisPlusConfig中配置相关的Interceptor和DataSource。
java
@Configuration
public class MybatisPlusConfig {
@Autowired
private DataSource dataSource;
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 配置分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
@Bean(name = "myRoutingDataSource")
public DataSource myRoutingDataSource() throws SQLException {
Map<String, DataSource> dataSourceMap = new HashMap<>(3);
dataSourceMap.put("master", dataSource);
dataSourceMap.put("slave0", createDataSource("jdbc:mysql://127.0.0.1:3307/test?useSSL=false&serverTimezone=UTC", "root", "123456"));
dataSourceMap.put("slave1", createDataSource("jdbc:mysql://127.0.0.1:3308/test?useSSL=false&serverTimezone=UTC", "root", "123456"));
ShardingRuleConfiguration shardingRuleConfiguration = new ShardingRuleConfiguration();
shardingRuleConfiguration.setDefaultDataSourceName("master");
// 配置分片规则
shardingRuleConfiguration.setDefaultDatabaseShardingStrategyConfig(new StandardShardingStrategyConfiguration("user_id", new ModuloShardingTableAlgorithm()));
shardingRuleConfiguration.setDefaultTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("user_id", new ModuloShardingTableAlgorithm()));
// 配置读写分离规则
shardingRuleConfiguration.setMasterSlaveRuleConfigs(Collections.singletonList(new MasterSlaveRuleConfiguration("ms0", "master", Arrays.asList("slave0", "slave1"))));
return ShardingSphereDataSourceFactory.createDataSource(dataSourceMap, Collections.singleton(shardingRuleConfiguration), new Properties());
}
private DataSource createDataSource(final String url, final String username, final String password) {
HikariDataSource result = new HikariDataSource();
result.setDriverClassName("com.mysql.cj.jdbc.Driver");
result.setJdbcUrl(url);
result.setUsername(username);
result.setPassword(password);
return result;
}
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean();
factoryBean.setDataSource(myRoutingDataSource());
factoryBean.setPlugins(mybatisPlusInterceptor());
return factoryBean.getObject();
}
@Bean
public SqlSessionTemplate sqlSessionTemplate() throws Exception {
return new SqlSessionTemplate(sqlSessionFactory());
}
}
在这个配置中,我们创建了一个myRoutingDataSource,用于管理我们的多数据源。在这里,我们将master库作为默认数据源,然后配置了两个从库(slave0和slave1)。
接着,我们还需要配置分片规则和读写分离规则。这里,我们简单地配置了一下按照user_id字段进行分片,并按照轮询策略进行负载均衡的读写分离规则。
最后,在我们的Mapper接口中,我们可以使用@DS注解来指定数据源。
less
public interface UserMapper extends BaseMapper<User> {
@DS("master") // 指定数据源为主库
@Override
int insert(User entity);
@DS("slave") // 指定数据源为从库
@Override
User selectById(Serializable id);
@DS("slave")
List<User> selectListByUserId(Integer userId);
}
这样,我们就完成了基于SpringBoot、Mybatis Plus、ShardingSphere实现读写分离的方案!
补充:
- 在数据库中建立表时,需要按照分片规则进行建表。例如,我们按照
user_id
进行分片,则需要对每个分片建立对应的表,例如user_0
、user_1
等。在进行增删改查操作时,需要根据user_id
进行路由。 - 在进行读写分离时,需要考虑到数据同步的问题。即,当主库增加或修改数据时,需要同步到从库中。在ShardingSphere中,可以设置同步方式,例如异步或同步等。
- 在ShardingSphere中,除了读写分离外,还有更多的分片策略可供选择。例如,按照哈希值进行分片、按照范围进行分片等等。根据实际场景选择合适的分片策略可以更好地提升性能。
- 在进行多数据源管理时,需要考虑到事务问题。例如,如果一个事务中需要涉及到多个数据源,就需要使用分布式事务来管理。ShardingSphere提供了XA、AT等分布式事务方案。
- 最好将ShardingSphere的配置分离出去,不要将其配置在application.yml中,这样更易于维护和管理。可以将配置写在单独的yaml文件中,并通过
spring.config.import
属性将其导入到SpringBoot中,例如:
yaml
# sharding-jdbc.yaml
spring:
shardingsphere:
# 配置数据源、分片规则和读写分离规则
然后,在application.yml中导入这个配置文件:
arduino
# application.ymlspring:
config:
import: classpath:sharding-jdbc.yml
- 在ShardingSphere中,如果有多个表需要采用相同的分片策略,可以使用逻辑表来简化配置。例如,我们有两个表
user
和order
,按照user_id
进行分片,可以这样配置:
yaml
# 配置逻辑表user_order
tables:
user_order:
actualDataNodes: ds${0..1}.user_${0..3} # 分片规则# 其他配置
- 在进行数据分片时,需要考虑到数据分布的均衡问题。如果某个分片的数据量过大,会导致性能下降。可以考虑将分片键设计得更加合理,以实现数据分布的均衡。
- 在进行读写分离时,需要考虑到数据同步的问题。如果在从库上发生了读取操作,但是在主库中进行了写入操作,那么数据就会出现不一致的情况。可以考虑使用异步复制或半同步复制等机制来解决这个问题。
- 在ShardingSphere中,可以使用
tracing-enabled
属性来启用分片日志,以便于定位错误和问题。 - 最后,需要注意分片的成本和维护的难度。尽管分片可以提高系统性能,但是需要付出更多的成本和维护的难度。在进行分片之前,需要对系统架构进行全面的评估,并权衡利弊。