1.读写分离
pom文件引入依赖
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.1.0</version>
</dependency>
配置文件加上主、从数据库的配置。给从库增加一个只读账号,用只读账号进行读取数据。
# 配置真实数据源
spring.shardingsphere.datasource.names=master,slave1
# 配置第1个数据源
# type必填
spring.shardingsphere.datasource.master.type=com.zaxxer.hikari.HikariDataSource
# 数据连接名称是jdbcUrl。用url会报错
spring.shardingsphere.datasource.master.jdbc-url=jdbc:mysql://localhost:3306/my?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=GMT
spring.shardingsphere.datasource.master.username=root
spring.shardingsphere.datasource.master.password=123456
spring.shardingsphere.datasource.master.hikari.maximum-pool-size=150
spring.shardingsphere.datasource.master.hikari.minimum-idle=100
# 配置第2个数据源
spring.shardingsphere.datasource.slave1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.slave1.jdbc-url=jdbc:mysql://localhost:3306/my?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=GMT
spring.shardingsphere.datasource.slave1.username=root
spring.shardingsphere.datasource.slave1.password=123456
spring.shardingsphere.datasource.slave1.hikari.maximum-pool-size=200
spring.shardingsphere.datasource.slave1.hikari.minimum-idle=100
# 配置主从逻辑数据源,读写分离规则, master主库,slave从库
spring.shardingsphere.masterslave.name=ms
spring.shardingsphere.masterslave.master-data-source-name=master
spring.shardingsphere.masterslave.slave-data-source-names=slave1
# 打印sql语句。在上线后,观察无问题,可去掉。
spring.shardingsphere.props.sql.show=true
配置完成后,重启应用。
2.权重配置
由于之前导入的4.1版本不支持权重,即使自定义了策略也没有生效。所以就用了5.1.1的版本,至于为什么不用最新版本……
也是两步,一个是pom导入,一个是配置。按照官网给出的配置就可以。这里给出我的配置。
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
<version>5.1.1</version>
</dependency>
配置文件
# 配置真实数据源
spring.shardingsphere.datasource.names=master,slave1,slave2
# 配置第 1 个数据源
spring.shardingsphere.datasource.master.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.master.jdbc-url=jdbc:mysql://localhost:3306/my?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=GMT
spring.shardingsphere.datasource.master.username=root
spring.shardingsphere.datasource.master.password=123456
spring.shardingsphere.datasource.master.hikari.maximum-pool-size=150
spring.shardingsphere.datasource.master.hikari.minimum-idle=100
# 配置第 2 个数据源
spring.shardingsphere.datasource.slave1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.slave1.jdbc-url=jdbc:mysql://localhost:3306/my_slave?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=GMT
spring.shardingsphere.datasource.slave1.username=root
spring.shardingsphere.datasource.slave1.password=123456
spring.shardingsphere.datasource.slave1.hikari.maximum-pool-size=200
spring.shardingsphere.datasource.slave1.hikari.minimum-idle=100
# 配置第 3 个数据源
spring.shardingsphere.datasource.slave2.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.slave2.jdbc-url=jdbc:mysql://localhost:3306/my_slave?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=GMT
spring.shardingsphere.datasource.slave2.username=root
spring.shardingsphere.datasource.slave2.password=123456
spring.shardingsphere.datasource.slave2.hikari.maximum-pool-size=150
spring.shardingsphere.datasource.slave2.hikari.minimum-idle=100
# 读写分离类型,如: Static,Dynamic
spring.shardingsphere.rules.readwrite-splitting.data-sources.ms.type=Static
# 写数据源,一般为主库。把该属性放在 [ms]的[prop]下,才能正确识别。[ms]为数据源名称,随便取
spring.shardingsphere.rules.readwrite-splitting.data-sources.ms.props.write-data-source-name=master
spring.shardingsphere.rules.readwrite-splitting.data-sources.ms.props.read-data-source-names=slave1,slave2
# 负载均衡算法名称,和下面的具体配置前缀保持一致
spring.shardingsphere.rules.readwrite-splitting.data-sources.ms.load-balancer-name=weight
# 负载均衡算法配置
spring.shardingsphere.rules.readwrite-splitting.load-balancers.weight.type=WEIGHT
spring.shardingsphere.rules.readwrite-splitting.load-balancers.weight.props.slave1=1
spring.shardingsphere.rules.readwrite-splitting.load-balancers.weight.props.slave2=2
# 5.1.1版本开启sql。和4.1版本不同
spring.shardingsphere.props.sql-show=true
2.1通过代码找到配置写法
由于官方只给出了最新版本的文档,我配置的又一直没有生效。然后我发现其实可以直接看代码,比如说随便配置,启动后报错,就点开报错的类,基本上就能找到对应的注入方法。对应的属性等等。
3.读写分离不生效
经过上一步,我确定sharding已经接管了数据源,并成功读取了我的配置。但测试时一直只读写库,也就是从主库读取,而不从我配置的读库中读取。
先给结论:因为我用的是findById方法测试,而这个方法的底层实现是SimpleJpaRepository类。这个类有Spring的事务注解,所以无论是读取还是写入,都会进入事务。进入事务的方法都会走主库。
所以读写分离其实是生效了的,只要我自定义一个查询方法测试,就会按照我的配置查库。
但是我在第一步时,也是用这个方法进行测试的,当时就很顺利,配置完以后读取都是走的从库。所以我就一直以为是配置没有生效,搞了老半天。这是为什么呢。我就开始在4.1和5.1之间一直测试,一直debug,找出二者的不同。满打满算找了绝对不止一天。
在ShardingSphere的4.1版本中,事务处理是通过AbstractConnectionAdapter类来实现的。该类负责拦截数据库连接的相关操作,并在事务开始时将数据源设置为写库。
然而,在4.1版本中,虽然开启了事务,但查询操作仍然会默认从读库中进行查询。这是因为读写分离的实现方式在4.1版本中是通过基于Hint的方式实现的,即通过特定的Hint注解将查询路由到读库。而在开启事务的情况下,ShardingSphere会忽略该Hint注解,仍然将查询路由至读库。
在ShardingSphere的5.1版本中,对事务处理逻辑进行了改进,引入了新的类ShardingSphereConnection来实现AbstractConnectionAdapter抽象类,并重写了开启事务的方法。这个改进使得在开启事务时,查询操作也会被路由到写库,以保证数据的一致性。
4.其他
我记得当时排查到还有一个方法是,判断querys是否包含当前方法,如果包含则查询,不包含就会走事务。但是现在找不到了,所以就这样吧。
还有就是查到事务也是因为在上面这个方法中,发现有的方法是包含的有的方法是不包含的,于是我之前一直findById测试,然后就换了query包含的测试,就发现是走的从库。读写分离是生效的。才开始4、5版本对比,看为什么4版本不会走到事务开启。原来4、5都会开启事务。