ShardingSphere5.x.x(最新版)配置MySQL读写分离
使用ShardingSphere-JDBC
配置项目的读写分离(仅包含ShardingSphere-JDBC相关配置内容)
作者这里使用springboot2.x.x
整合ShardingSphere-JDBC实现读写分离,注意的是,作者使用的springboot版本是2.7.10,支持ShardingSphere 5.2.x和ShardingSphere 5.3.x的配置,注意的是如果使用springboot3.0
以上的版本,可能只有ShardingSphere 5.3.x支持。
1. ShardingSphere 5.2.x
在 5.3.0
版本以前,ShardingSphere-JDBC
同时支持 Java API
、YAML
、Spring Boot Starter
和 Spring Namespace
等配置方式。
因此可以使用shardingsphere-jdbc-core-spring-boot-starter
进行配置,本节使用starter 5.2.1进行项目配置。
ShardingSphere其他相关介绍查看其他博客文章。
可以参考官方文档:ShardingSphere 5.2.1 文档
切记,需要选择合适的版本
1.1 引入依赖坐标
引入starter坐标的最后一个版本(官方不再维护starter版本)
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
<version>5.2.1</version>
</dependency>
覆盖springboot2.x
的SnakeYAML依赖,如果你是sringboot3.x
,可能不需要,作者没有尝试。
原因参考github上的Issues:https://github.com/apache/shardingsphere/issues/21476
引入依赖覆盖springboot
默认版本
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.33</version>
</dependency>
1.2 在springboot配置文件中做相应的配置
参考官方文档,记得选对应版本:Spring Boot Starter 配置
1.2.1 数据源配置
注意,使用数据源配置需要去掉所有spring.datasource
下的所有配置
并且,数据源的starter坐标可能出现问题,例如druid的starter坐标,参考github上的常见问题:https://github.com/apache/shardingsphere/wiki/FAQ#jdbc
官网常见问题内容少于项目开源的github上的常见问题,建议遇到问题前往github查看或者提问,提问请符合官方提问模板并使用英语提问。
因此,我们下面使用druid配置,因此需要导入druid的非starter依赖
<!-- 禁用druid的starter依赖 -->
<!--<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.16</version>
</dependency>-->
<!-- 使用ShardingSphere读写分离不能使用druid的starter -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.18</version>
</dependency>
配置参考官方文档:
spring.shardingsphere.datasource.names= # 真实数据源名称,多个数据源用逗号区分
# <actual-data-source-name> 表示真实数据源名称
spring.shardingsphere.datasource.<actual-data-source-name>.type= # 数据库连接池全类名
spring.shardingsphere.datasource.<actual-data-source-name>.driver-class-name= # 数据库驱动类名,以数据库连接池自身配置为准
spring.shardingsphere.datasource.<actual-data-source-name>.jdbc-url= # 数据库 URL 连接,以数据库连接池自身配置为准
spring.shardingsphere.datasource.<actual-data-source-name>.username= # 数据库用户名,以数据库连接池自身配置为准
spring.shardingsphere.datasource.<actual-data-source-name>.password= # 数据库密码,以数据库连接池自身配置为准
spring.shardingsphere.datasource.<actual-data-source-name>.<xxx>= # ... 数据库连接池的其它属性
注意:当使用 ShardingSphere JDBC 时,JDBC 池的属性名取决于各自 JDBC 池自己的定义,并不由 ShardingSphere 硬定义,相关的处理可以参考类
org.apache.shardingsphere.infra.datasource.pool.creator.DataSourcePoolCreator
。例如对于 Alibaba Druid 1.2.9 而言,使用url
代替如下示例中的jdbc-url
是预期行为。
示例如下:
spring:
shardingsphere:
datasource:
names: master,slave
# 主数据源
master:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.60.100:3307/db1
username: root
password: "you_password"
# 从数据源
slave:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.60.100:3308/db2
username: root
password: "you_password"
1.2.2 读写分离配置
这里我们配置静态读写分离
参考官方文档:读写分离 :: ShardingSphere (apache.org)
spring.shardingsphere.datasource.names= # 省略数据源配置,请参考使用手册
spring.shardingsphere.rules.readwrite-splitting.data-sources.<readwrite-splitting-data-source-name>.static-strategy.write-data-source-name= # 写库数据源名称
spring.shardingsphere.rules.readwrite-splitting.data-sources.<readwrite-splitting-data-source-name>.static-strategy.read-data-source-names= # 读库数据源列表,多个从数据源用逗号分隔
spring.shardingsphere.rules.readwrite-splitting.data-sources.<readwrite-splitting-data-source-name>.load-balancer-name= # 负载均衡算法名称
# 负载均衡算法配置
spring.shardingsphere.rules.readwrite-splitting.load-balancers.<load-balance-algorithm-name>.type= # 负载均衡算法类型
spring.shardingsphere.rules.readwrite-splitting.load-balancers.<load-balance-algorithm-name>.props.xxx= # 负载均衡算法属性配置
我的示例:
spring:
shardingsphere:
rules:
readwrite-splitting:
data-sources:
read-write-datasource:
static-strategy:
# 写库数据源名称
write-data-source-name: master
# 读库数据源列表,多个从数据源用逗号分隔
read-data-source-names: slave
# 负载均衡算法名称
load-balancer-name: round_robin
# 负载均衡算法配置
load-balancers:
round_robin:
# 负载均衡算法类型
type: ROUND_ROBIN
# 负载均衡算法属性配置
# props:
1.2.3 便于调试的附加配置
spring:
shardingsphere:
props:
sql:
show: true #开启SQL显示,默认false
其他配置,请参考官方文档
2. ShardingSphere 5.3.x
升级ShardingSphere 5.3.x
后取消了Spring Boot Starter
和 Spring Namespace
等配置,因此我们使用导入配置文件的方式。
其他参考官方文档:概览 :: ShardingSphere (apache.org)(注意选择文档版本)
2.1 引入当前最新依赖坐标
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core</artifactId>
<version>5.3.2</version>
</dependency>
如果使用的是springboot2.x
同上,覆盖snakeyaml,原因相同。
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.33</version>
</dependency>
2.2 导入相应的配置
参考官方文档,在springboot
的配置文件加入相应配置信息:ShardingSphere-JDBC :: ShardingSphere (apache.org)
注意:datasource最好不再加其他配置,否则可能出现未知错误
# 配置 DataSource Driver
spring.datasource.driver-class-name=org.apache.shardingsphere.driver.ShardingSphereDriver
# 指定 YAML 配置文件
spring.datasource.url=jdbc:shardingsphere:classpath:xxx.yaml
我的配置,我配置文件命名为sharding-config.yaml
:
spring:
datasource:
driver-class-name: org.apache.shardingsphere.driver.ShardingSphereDriver
url: jdbc:shardingsphere:classpath:sharding-config.yaml
2.2.1 数据源配置
同上,去掉druid的starter坐标,并且需要修改配置的一些项目
官方配置:
dataSources: # 数据源配置,可配置多个 <data-source-name>
<data_source_name>: # 数据源名称
dataSourceClassName: # 数据源完整类名
driverClassName: # 数据库驱动类名,以数据库连接池自身配置为准
jdbcUrl: # 数据库 URL 连接,以数据库连接池自身配置为准
username: # 数据库用户名,以数据库连接池自身配置为准
password: # 数据库密码,以数据库连接池自身配置为准
# ... 数据库连接池的其它属性
我的配置:
dataSources:
master:
dataSourceClassName: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.60.100:3307/db1
username: root
password: "you_password"
# ... 数据库连接池的其它属性
slave:
dataSourceClassName: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.60.100:3308/db2
username: root
password: "you_password"
# ... 数据库连接池的其它属性
2.2.2 读写分离配置
这里我们配置静态读写分离
参考官方文档:读写分离 :: ShardingSphere (apache.org)
值得注意的是,官方文档有错误,在参数解释中,一些配置项使用了_分隔命名,但是会运行会显示解析错误,因此需要改为驼峰命名,官方文档的示例是正确的:
官方文档错误示例:
官方文档正确示例:
不知道为什么,官方文档有误,至少作者使用的5.3.2版本需要驼峰命名。
改正后的静态读写的官方示例:
rules:
- !READWRITE_SPLITTING
dataSources:
<data_source_name> (+): # 读写分离逻辑数据源名称
staticStrategy: # 读写分离类型
writeDataSourceName: # 写库数据源名称
readDataSourceNames: # 读库数据源名称,多个从数据源用逗号分隔
loadBalancerName: # 负载均衡算法名称
# 负载均衡算法配置
loadBalancers:
<load_balancer_name> (+): # 负载均衡算法名称
type: # 负载均衡算法类型
props: # 负载均衡算法属性配置
# ...
我的示例:
rules:
- !READWRITE_SPLITTING
dataSources:
# 读写分离逻辑数据源名称
readwrite_ds:
# 读写分离类型
staticStrategy:
# 写库数据源名称
writeDataSourceName: master
# 读库数据源名称,多个从数据源用逗号分隔,或者使用数组表示
readDataSourceNames:
- slave
# 负载均衡算法名称
loadBalancerName: round_robin
# 负载均衡算法配置
loadBalancers:
# 负载均衡算法名称
round_robin:
# 负载均衡算法类型
type: ROUND_ROBIN
# 负载均衡算法属性配置
# props:
# ...
2.2.3 便于调试的附加配置
同上
props:
sql-show: true
更多配置请参考官方文档
3. 单机模式下修改数据源的问题
使用druid
正确配置数据源并运行后,发现数据源hikariDataSource
依旧被加载,因此会加载两个数据源:
在查询github相关问题后,发现了这个Issue:关于默认连接池的困惑问题 ·问题 #24348 ·Apache / Shardingsphere (github.com)
看起来,这个问题没有解决,应该对运行没有影响。
4. 错误汇总
4.1 新版在springboot2 中没有覆盖SnakeYAML
错误信息:
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2023-05-18 10:54:14.320 ERROR 22560 --- [ restartedMain] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
An attempt was made to call a method that does not exist. The attempt was made from the following location:
org.apache.shardingsphere.infra.util.yaml.constructor.ShardingSphereYamlConstructor$1.<init>(ShardingSphereYamlConstructor.java:45)
The following method did not exist:
···
解决方案:覆盖SnakeYAML
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.33</version>
</dependency>
方案来源:https://github.com/apache/shardingsphere/issues/21476
4.2 使用了druid的starter依赖
使用了druid的starter依赖,或者设置了spring.datasource.type为druid
错误信息:
2023-05-18 10:58:10.015 ERROR 29788 --- [ restartedMain] com.alibaba.druid.pool.DruidDataSource : testWhileIdle is true, validationQuery not set
或者
···
2023-05-18 11:00:14.900 ERROR 24408 --- [reate-664989078] com.alibaba.druid.pool.DruidDataSource : create connection RuntimeException
java.lang.NullPointerException: null
at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1764) ~[druid-1.2.18.jar:na]
at com.alibaba.druid.pool.DruidDataSource$CreateConnectionThread.run(DruidDataSource.java:2942) ~[druid-1.2.18.jar:na]
···
解决方案:禁用druid
的starter
坐标,去掉spring.datasource.type
内容
<!-- 禁用druid的starter依赖 -->
<!--<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.16</version>
</dependency>-->
<!-- 使用ShardingSphere读写分离不能使用druid的starter -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.18</version>
</dependency>
方案来源:https://github.com/apache/shardingsphere/wiki/FAQ#jdbc
4.3 配置信息错误1 数据源相关配置错误
druid的数据源配置项,例如HikariDataSource
是jdbcUrl
,而druid
是url
,请仔细参考官方文档信息。
错误信息:
2023-05-18 11:03:52.326 ERROR 25756 --- [ restartedMain] com.alibaba.druid.pool.DruidDataSource : {dataSource-1} init error
java.sql.SQLException: url not set
at com.alibaba.druid.pool.DruidDataSource.resolveDriver(DruidDataSource.java:1274) ~[druid-1.2.18.jar:na]
at com.alibaba.druid.pool.DruidDataSource.init(DruidDataSource.java:899) ~[druid-1.2.18.jar:na]
at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:1463) ~[druid-1.2.18.jar:na]
at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:1459) ~[druid-1.2.18.jar:na]
at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:83) ~[druid-1.2.18.jar:na]
at org.apache.shardingsphere.infra.datasource.state.DataSourceStateManager.checkState(DataSourceStateManager.java:84) ~[shardingsphere-infra-common-5.3.2.jar:5.3.2]
at org.apache.shardingsphere.infra.datasource.state.DataSourceStateManager.initState(DataSourceStateManager.java:79) ~[shardingsphere-infra-common-5.3.2.jar:5.3.2]
···
解决方案:仔细检查配置信息
方案来源:数据源配置 :: ShardingSphere (apache.org)
4.4 配置信息错误2 配置文件配置项错误
可能1:参考官方文档过程中,目前文档中有配置项是下划线分隔,官方文档错误导致的问题
可能2:读者不仔细参考相关文档,导致yaml顺序层次错误
可能3:读者参考的官方文档与使用的版本不匹配导致的配置项错误
错误信息:
2023-05-18 11:11:50.063 ERROR 16664 --- [ restartedMain] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Exception during pool initialization.
org.yaml.snakeyaml.constructor.ConstructorException: Cannot create property=rules for JavaBean=org.apache.shardingsphere.infra.yaml.config.pojo.YamlRootConfiguration@74525630
in 'reader', line 1, column 1:
dataSources:
^
Cannot create property=dataSources for JavaBean=org.apache.shardingsphere.readwritesplitting.yaml.config.YamlReadwriteSplittingRuleConfiguration@a85bdef
in 'reader', line 17, column 5:
- !READWRITE_SPLITTING
^
Cannot create property=static_strategy for JavaBean=org.apache.shardingsphere.readwritesplitting.yaml.config.rule.YamlReadwriteSplittingDataSourceRuleConfiguration@1b2181f6
in 'reader', line 22, column 9:
static_strategy:
^
Unable to find property 'static_strategy' on class: org.apache.shardingsphere.readwritesplitting.yaml.config.rule.YamlReadwriteSplittingDataSourceRuleConfiguration
in 'reader', line 24, column 11:
writeDataSourceName: master
^
in 'reader', line 20, column 7:
readwrite_ds:
^
in 'reader', line 17, column 3:
- !READWRITE_SPLITTING
^
at org.yaml.snakeyaml.constructor.Constructor$ConstructMapping.constructJavaBean2ndStep(Constructor.java:321) ~[snakeyaml-1.33.jar:na]
at org.yaml.snakeyaml.constructor.Constructor$ConstructMapping.construct(Constructor.java:207) ~[snakeyaml-1.33.jar:na]
at org.yaml.snakeyaml.constructor.Constructor$ConstructYamlObject.construct(Constructor.java:358) ~[snakeyaml-1.33.jar:na]
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObjectNoCheck(BaseConstructor.java:270) ~[snakeyaml-1.33.jar:na]
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:253) ~[snakeyaml-1.33.jar:na]
at org.yaml.snakeyaml.constructor.BaseConstructor.constructDocument(BaseConstructor.java:207) ~[snakeyaml-1.33.jar:na]
at org.yaml.snakeyaml.constructor.BaseConstructor.getSingleData(BaseConstructor.java:191) ~[snakeyaml-1.33.jar:na]
···
解决方案:仔细检查,配置项信息,查看官方文档或者github的Issues寻找正确的配置信息,注意使用的版本;当前,截至文章发出前(2023.5.18)最新版的参考文档的读写分离配置项有错误,下划线分隔需要改为驼峰命名,详细内容见上面配置相关内容。
方案来源:https://github.com/apache/shardingsphere/issues/25191