告别配置踩坑:SpringBoot3 + MyBatis-Plus 3.5.5 整合 ShardingJDBC 5.5.0 读写分离保姆级教程
SpringBoot3 + MyBatis-Plus 3.5.5 整合 ShardingJDBC 5.5.0 实现高可用读写分离实战指南
最近在重构公司的一个电商项目时,遇到了数据库性能瓶颈。当促销活动开始,系统瞬间涌入大量用户查询请求,主库CPU直接飙到90%以上,导致整个系统响应变慢。经过技术调研,我们决定采用ShardingJDBC实现读写分离来分担主库压力。但在整合过程中踩了不少坑,特别是SpringBoot3与ShardingJDBC 5.5.0的版本兼容性问题。本文将分享我们最终落地的完整方案,包含依赖管理、配置细节和实战技巧。
1. 环境准备与依赖管理
在开始之前,需要确认开发环境满足以下要求:
- JDK 17+(SpringBoot3的最低要求)
- Maven 3.6.3+
- MySQL 8.0+(推荐使用最新稳定版)
1.1 关键依赖版本选择
SpringBoot3与ShardingJDBC的版本兼容性是个大坑。经过测试,只有ShardingJDBC 5.4.1及以上版本才能完美兼容SpringBoot3。以下是必须注意的核心依赖:
<properties>
<java.version>17</java.version>
<spring-boot.version>3.2.4</spring-boot.version>
<mybatis-plus.version>3.5.5</mybatis-plus.version>
<shardingsphere.version>5.5.0</shardingsphere.version>
</properties>
1.2 POM文件关键配置
完整的依赖配置需要考虑排除冲突的传递依赖。特别是MyBatis-Plus和ShardingJDBC自带的一些测试工具包:
<dependencies>
<!-- SpringBoot基础依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 使用Undertow替代Tomcat提升性能 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<!-- MyBatis-Plus配置(注意排除冲突) -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
<exclusions>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
</exclusion>
<exclusion>
<artifactId>mybatis</artifactId>
<groupId>org.mybatis</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- ShardingJDBC核心依赖 -->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc</artifactId>
<version>${shardingsphere.version}</version>
<exclusions>
<exclusion>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-test-util</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
提示:建议使用dependencyManagement统一管理SpringBoot相关依赖版本,避免潜在的版本冲突问题。
2. 核心配置详解
2.1 application.yml关键配置
SpringBoot应用需要做以下调整才能正确集成ShardingJDBC:
spring:
main:
allow-bean-definition-overriding: true # 必须开启
application:
name: order-service
datasource:
driver-class-name: org.apache.shardingsphere.driver.ShardingSphereDriver
url: jdbc:shardingsphere:classpath:sharding.yaml
配置项说明:
| 配置项 | 必须 | 说明 |
|---|---|---|
| allow-bean-definition-overriding | 是 | 允许Bean定义覆盖,解决ShardingJDBC与SpringBoot自动配置冲突 |
| driver-class-name | 是 | 使用ShardingSphere提供的驱动类 |
| url | 是 | 指向ShardingSphere的配置文件路径 |
2.2 sharding.yaml完整配置
这是整个读写分离的核心配置文件,需要特别注意rules部分的配置顺序:
dataSources:
ds_master:
driverClassName: com.mysql.cj.jdbc.Driver
dataSourceClassName: com.zaxxer.hikari.HikariDataSource
jdbcUrl: jdbc:mysql://master-host:3306/order_db?useSSL=false&serverTimezone=UTC
username: root
password: master-password
connectionTimeout: 30000
maximumPoolSize: 20
ds_slave1:
driverClassName: com.mysql.cj.jdbc.Driver
dataSourceClassName: com.zaxxer.hikari.HikariDataSource
jdbcUrl: jdbc:mysql://slave1-host:3306/order_db?useSSL=false&serverTimezone=UTC
username: root
password: slave-password
connectionTimeout: 30000
maximumPoolSize: 20
rules:
- !SINGLE
tables:
- "*.*"
defaultDataSource: ds_master
- !READWRITE_SPLITTING
dataSources:
readwrite_ds:
writeDataSourceName: ds_master
readDataSourceNames:
- ds_slave1
transactionalReadQueryStrategy: PRIMARY
loadBalancerName: round_robin
loadBalancers:
round_robin:
type: ROUND_ROBIN
props:
sql-show: true # 开发环境建议开启,生产环境关闭
关键配置解析:
- !SINGLE规则 :必须放在第一位,用于定义默认数据源和表映射关系
- !READWRITE_SPLITTING规则 :定义读写分离策略
- loadBalancers :定义读库的负载均衡策略(支持ROUND_ROBIN和RANDOM)
3. 高级功能实现
3.1 强制走主库的注解实现
某些业务场景(如刚写入立即查询)需要强制走主库,可以通过HintManager实现:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Master {
}
@Aspect
@Component
@Slf4j
public class MasterRouteAspect {
@Around("@annotation(com.yourpackage.Master)")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
HintManager hintManager = null;
try {
hintManager = HintManager.getInstance();
hintManager.setWriteRouteOnly();
return joinPoint.proceed();
} finally {
if (hintManager != null) {
hintManager.close();
}
}
}
}
使用方法:在Service方法上添加@Master注解即可强制走主库:
@Service
public class OrderServiceImpl implements OrderService {
@Master
public Order getOrderById(Long orderId) {
// 该方法会强制走主库查询
return orderMapper.selectById(orderId);
}
}
3.2 读写分离策略调优
ShardingJDBC提供了多种读写分离策略,可以根据业务特点进行配置:
rules:
- !READWRITE_SPLITTING
dataSources:
readwrite_ds:
writeDataSourceName: ds_master
readDataSourceNames:
- ds_slave1
- ds_slave2
transactionalReadQueryStrategy: FIXED # 可选值:PRIMARY/FIXED/DYNAMIC
loadBalancerName: round_robin
策略对比:
| 策略 | 说明 | 适用场景 |
|---|---|---|
| PRIMARY | 事务内所有读操作走主库 | 强一致性要求高的场景 |
| FIXED | 事务内第一个读操作决定后续读操作的路由 | 平衡一致性与性能 |
| DYNAMIC | 每个读操作独立路由 | 对一致性要求不高的场景 |
4. 生产环境最佳实践
4.1 监控与健康检查
建议集成SpringBoot Actuator监控数据源状态:
management:
endpoints:
web:
exposure:
include: health,info,metrics
endpoint:
health:
show-details: always
健康检查结果示例:
{
"status": "UP",
"components": {
"db": {
"status": "UP",
"details": {
"database": "MySQL",
"master": {
"status": "UP",
"connection": "alive"
},
"slave1": {
"status": "UP",
"connection": "alive"
}
}
}
}
}
4.2 性能优化建议
-
连接池配置 :根据实际负载调整HikariCP参数
dataSources: ds_master: maximumPoolSize: 20 minimumIdle: 5 idleTimeout: 600000 maxLifetime: 1800000 -
SQL打印控制 :生产环境关闭SQL打印
props: sql-show: false sql-simple: true # 简化日志输出 -
读写比例调整 :根据业务特点配置读库权重
loadBalancers: weight_balancer: type: WEIGHT props: ds_slave1: 2 ds_slave2: 1
4.3 常见问题排查
问题1 :启动时报 Table 'xxx' doesn't exist
解决方案:确保在rules中正确配置了!SINGLE规则,并且defaultDataSource指向正确的主库。
问题2 :读写分离不生效,所有查询都走主库
检查点:
- 确认sharding.yaml中!READWRITE_SPLITTING规则配置正确
- 检查是否在事务中执行查询(默认事务内走主库)
- 确认没有使用@Master注解
问题3 :性能没有明显提升
可能的优化方向:
- 增加从库数量
- 调整负载均衡策略
- 优化SQL查询(添加合适索引)
更多推荐

所有评论(0)