shardingsphere: SpringBoot整合shardingjdbc实现读写分离

1. 引入jar包

<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
    <version>5.2.0</version>
</dependency>

2. 编写application.properties

#模式设置
spring.shardingsphere.mode.type=Standalone
#日志打印
spring.shardingsphere.props.sql-show=true

# 配置真实数据源
spring.shardingsphere.datasource.names=write,read1,read2
# 配置第 1 个数据源
spring.shardingsphere.datasource.write.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.write.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.write.jdbc-url=jdbc:mysql://xx.xx.xxx.xx:3306/testdb?useUnicode=true&characterEncoding=utf8
spring.shardingsphere.datasource.write.username=root
spring.shardingsphere.datasource.write.password=xxxxxx
# 配置第 2 个数据源
spring.shardingsphere.datasource.read1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.read1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.read1.jdbc-url=jdbc:mysql://xx.xx.xxx.xx:3307/testdb?useUnicode=true&characterEncoding=utf8
spring.shardingsphere.datasource.read1.username=root
spring.shardingsphere.datasource.read1.password=xxxxxx
# 配置第 3 个数据源
spring.shardingsphere.datasource.read2.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.read2.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.read2.jdbc-url=jdbc:mysql://xx.xx.xxx.xx:3308/testdb?useUnicode=true&characterEncoding=utf8
spring.shardingsphere.datasource.read2.username=root
spring.shardingsphere.datasource.read2.password=xxxxxx

#读写分离配置
#写库数据源
spring.shardingsphere.rules.readwrite-splitting.data-sources.readwrite_ds.static-strategy.write-data-source-name=write
#读库数据源(多个从数据源用逗号分隔)
spring.shardingsphere.rules.readwrite-splitting.data-sources.readwrite_ds.static-strategy.read-data-source-names=read1,read2

#负载均衡配置
spring.shardingsphere.rules.readwrite-splitting.data-sources.readwrite_ds.load-balancer-name=round_robin
#负载均衡算法
spring.shardingsphere.rules.readwrite-splitting.load-balancers.round_robin.type=ROUND_ROBIN

3. 事务测试

3.1 测试代码

    @RequestMapping("/insertData")
    public Object test2() throws InterruptedException {
    
    
        int random = (int) (Math.random() * 1000 + 1);
        String randomUsername = "王二" + random;
        User user = new User();
        user.setUname(randomUsername);
        int insert = userMapper.insert(user);
        if (insert > 0) {
    
    
            log.info("数据插入成功:{}", JSONObject.toJSONString(user));
        }
        //数据查询
        List<User> queryUsername1 = userMapper.selectList(new QueryWrapper<User>().eq("uname", randomUsername));
        log.info("数据查询1:{}", JSONObject.toJSONString(queryUsername1));
        List<User> queryUsername2 = userMapper.selectList(new QueryWrapper<User>().eq("uname", randomUsername));
        log.info("数据查询2:{}", JSONObject.toJSONString(queryUsername2));

        return queryUsername1;
    }

日志查看

2022-10-31 14:48:33.999  INFO 23376 --- [nio-8080-exec-1] ShardingSphere-SQL                       : Logic SQL: INSERT INTO t_user  ( uname )  VALUES  ( ? )
2022-10-31 14:48:33.999  INFO 23376 --- [nio-8080-exec-1] ShardingSphere-SQL                       : SQLStatement: MySQLInsertStatement(super=InsertStatement(super=AbstractSQLStatement(parameterCount=1, parameterMarkerSegments=[ParameterMarkerExpressionSegment(startIndex=41, stopIndex=41, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty)], commentSegments=[]), table=SimpleTableSegment(tableName=TableNameSegment(startIndex=12, stopIndex=17, identifier=IdentifierValue(value=t_user, quoteCharacter=NONE)), owner=Optional.empty, alias=Optional.empty), insertColumns=Optional[InsertColumnsSegment(startIndex=20, stopIndex=28, columns=[ColumnSegment(startIndex=22, stopIndex=26, identifier=IdentifierValue(value=uname, quoteCharacter=NONE), owner=Optional.empty)])], insertSelect=Optional.empty, values=[InsertValuesSegment(startIndex=39, stopIndex=43, values=[ParameterMarkerExpressionSegment(startIndex=41, stopIndex=41, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty)])]), setAssignment=Optional.empty, onDuplicateKeyColumns=Optional.empty)
2022-10-31 14:48:34.000  INFO 23376 --- [nio-8080-exec-1] ShardingSphere-SQL                       : Actual SQL: write ::: INSERT INTO t_user  ( uname )  VALUES  ( ? ) ::: [王二563]
2022-10-31 14:48:34.127  INFO 23376 --- [nio-8080-exec-1] c.q.p.controller.ShardingController      : 数据插入成功:{"id":23,"uname":"王二563"}
2022-10-31 14:48:34.216  INFO 23376 --- [nio-8080-exec-1] ShardingSphere-SQL                       : Logic SQL: SELECT  id,uname  FROM t_user 
 
 WHERE (uname = ?)
2022-10-31 14:48:34.216  INFO 23376 --- [nio-8080-exec-1] ShardingSphere-SQL                       : SQLStatement: MySQLSelectStatement(super=SelectStatement(super=AbstractSQLStatement(parameterCount=1, parameterMarkerSegments=[ParameterMarkerExpressionSegment(startIndex=49, stopIndex=49, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty)], commentSegments=[]), projections=ProjectionsSegment(startIndex=8, stopIndex=15, projections=[ColumnProjectionSegment(column=ColumnSegment(startIndex=8, stopIndex=9, identifier=IdentifierValue(value=id, quoteCharacter=NONE), owner=Optional.empty), alias=Optional.empty), ColumnProjectionSegment(column=ColumnSegment(startIndex=11, stopIndex=15, identifier=IdentifierValue(value=uname, quoteCharacter=NONE), owner=Optional.empty), alias=Optional.empty)], distinctRow=false), from=SimpleTableSegment(tableName=TableNameSegment(startIndex=23, stopIndex=28, identifier=IdentifierValue(value=t_user, quoteCharacter=NONE)), owner=Optional.empty, alias=Optional.empty), where=Optional[WhereSegment(startIndex=34, stopIndex=50, expr=BinaryOperationExpression(startIndex=41, stopIndex=49, left=ColumnSegment(startIndex=41, stopIndex=45, identifier=IdentifierValue(value=uname, quoteCharacter=NONE), owner=Optional.empty), right=ParameterMarkerExpressionSegment(startIndex=49, stopIndex=49, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty), operator==, text=uname = ?))], groupBy=Optional.empty, having=Optional.empty, orderBy=Optional.empty, combines=[]), table=Optional.empty, limit=Optional.empty, lock=Optional.empty, window=Optional.empty)
2022-10-31 14:48:34.216  INFO 23376 --- [nio-8080-exec-1] ShardingSphere-SQL                       : Actual SQL: read1 ::: SELECT  id,uname  FROM t_user 
 
 WHERE (uname = ?) ::: [王二563]
2022-10-31 14:48:34.751  INFO 23376 --- [nio-8080-exec-1] c.q.p.controller.ShardingController      : 数据查询1:[{"id":23,"uname":"王二563"}]
2022-10-31 14:48:34.756  INFO 23376 --- [nio-8080-exec-1] ShardingSphere-SQL                       : Logic SQL: SELECT  id,uname  FROM t_user 
 
 WHERE (uname = ?)
2022-10-31 14:48:34.756  INFO 23376 --- [nio-8080-exec-1] ShardingSphere-SQL                       : SQLStatement: MySQLSelectStatement(super=SelectStatement(super=AbstractSQLStatement(parameterCount=1, parameterMarkerSegments=[ParameterMarkerExpressionSegment(startIndex=49, stopIndex=49, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty)], commentSegments=[]), projections=ProjectionsSegment(startIndex=8, stopIndex=15, projections=[ColumnProjectionSegment(column=ColumnSegment(startIndex=8, stopIndex=9, identifier=IdentifierValue(value=id, quoteCharacter=NONE), owner=Optional.empty), alias=Optional.empty), ColumnProjectionSegment(column=ColumnSegment(startIndex=11, stopIndex=15, identifier=IdentifierValue(value=uname, quoteCharacter=NONE), owner=Optional.empty), alias=Optional.empty)], distinctRow=false), from=SimpleTableSegment(tableName=TableNameSegment(startIndex=23, stopIndex=28, identifier=IdentifierValue(value=t_user, quoteCharacter=NONE)), owner=Optional.empty, alias=Optional.empty), where=Optional[WhereSegment(startIndex=34, stopIndex=50, expr=BinaryOperationExpression(startIndex=41, stopIndex=49, left=ColumnSegment(startIndex=41, stopIndex=45, identifier=IdentifierValue(value=uname, quoteCharacter=NONE), owner=Optional.empty), right=ParameterMarkerExpressionSegment(startIndex=49, stopIndex=49, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty), operator==, text=uname = ?))], groupBy=Optional.empty, having=Optional.empty, orderBy=Optional.empty, combines=[]), table=Optional.empty, limit=Optional.empty, lock=Optional.empty, window=Optional.empty)
2022-10-31 14:48:34.756  INFO 23376 --- [nio-8080-exec-1] ShardingSphere-SQL                       : Actual SQL: read2 ::: SELECT  id,uname  FROM t_user 
 
 WHERE (uname = ?) ::: [王二563]
2022-10-31 14:48:35.300  INFO 23376 --- [nio-8080-exec-1] c.q.p.controller.ShardingController      : 数据查询2:[{"id":23,"uname":"王二563"}]

注意: 从上述日志中可以看到,在一次请求中,执行数据插入与数据查询时,数据插入操作的是write数据源,而数据读取操作的是另外两个read数据源,因为数据同步的问题,这样后续可能会存在重大隐患!

当我们给上述代码加上@Transactional注解后,再次执行观察日志

2022-10-31 14:53:27.866  INFO 18800 --- [nio-8080-exec-1] ShardingSphere-SQL                       : Logic SQL: INSERT INTO t_user  ( uname )  VALUES  ( ? )
2022-10-31 14:53:27.866  INFO 18800 --- [nio-8080-exec-1] ShardingSphere-SQL                       : SQLStatement: MySQLInsertStatement(super=InsertStatement(super=AbstractSQLStatement(parameterCount=1, parameterMarkerSegments=[ParameterMarkerExpressionSegment(startIndex=41, stopIndex=41, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty)], commentSegments=[]), table=SimpleTableSegment(tableName=TableNameSegment(startIndex=12, stopIndex=17, identifier=IdentifierValue(value=t_user, quoteCharacter=NONE)), owner=Optional.empty, alias=Optional.empty), insertColumns=Optional[InsertColumnsSegment(startIndex=20, stopIndex=28, columns=[ColumnSegment(startIndex=22, stopIndex=26, identifier=IdentifierValue(value=uname, quoteCharacter=NONE), owner=Optional.empty)])], insertSelect=Optional.empty, values=[InsertValuesSegment(startIndex=39, stopIndex=43, values=[ParameterMarkerExpressionSegment(startIndex=41, stopIndex=41, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty)])]), setAssignment=Optional.empty, onDuplicateKeyColumns=Optional.empty)
2022-10-31 14:53:27.866  INFO 18800 --- [nio-8080-exec-1] ShardingSphere-SQL                       : Actual SQL: write ::: INSERT INTO t_user  ( uname )  VALUES  ( ? ) ::: [王二737]
2022-10-31 14:53:28.892  INFO 18800 --- [nio-8080-exec-1] c.q.p.controller.ShardingController      : 数据插入成功:{"id":24,"uname":"王二737"}
2022-10-31 14:53:29.001  INFO 18800 --- [nio-8080-exec-1] ShardingSphere-SQL                       : Logic SQL: SELECT  id,uname  FROM t_user 
 
 WHERE (uname = ?)
2022-10-31 14:53:29.001  INFO 18800 --- [nio-8080-exec-1] ShardingSphere-SQL                       : SQLStatement: MySQLSelectStatement(super=SelectStatement(super=AbstractSQLStatement(parameterCount=1, parameterMarkerSegments=[ParameterMarkerExpressionSegment(startIndex=49, stopIndex=49, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty)], commentSegments=[]), projections=ProjectionsSegment(startIndex=8, stopIndex=15, projections=[ColumnProjectionSegment(column=ColumnSegment(startIndex=8, stopIndex=9, identifier=IdentifierValue(value=id, quoteCharacter=NONE), owner=Optional.empty), alias=Optional.empty), ColumnProjectionSegment(column=ColumnSegment(startIndex=11, stopIndex=15, identifier=IdentifierValue(value=uname, quoteCharacter=NONE), owner=Optional.empty), alias=Optional.empty)], distinctRow=false), from=SimpleTableSegment(tableName=TableNameSegment(startIndex=23, stopIndex=28, identifier=IdentifierValue(value=t_user, quoteCharacter=NONE)), owner=Optional.empty, alias=Optional.empty), where=Optional[WhereSegment(startIndex=34, stopIndex=50, expr=BinaryOperationExpression(startIndex=41, stopIndex=49, left=ColumnSegment(startIndex=41, stopIndex=45, identifier=IdentifierValue(value=uname, quoteCharacter=NONE), owner=Optional.empty), right=ParameterMarkerExpressionSegment(startIndex=49, stopIndex=49, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty), operator==, text=uname = ?))], groupBy=Optional.empty, having=Optional.empty, orderBy=Optional.empty, combines=[]), table=Optional.empty, limit=Optional.empty, lock=Optional.empty, window=Optional.empty)
2022-10-31 14:53:29.002  INFO 18800 --- [nio-8080-exec-1] ShardingSphere-SQL                       : Actual SQL: write ::: SELECT  id,uname  FROM t_user 
 
 WHERE (uname = ?) ::: [王二737]
2022-10-31 14:53:29.172  INFO 18800 --- [nio-8080-exec-1] c.q.p.controller.ShardingController      : 数据查询1:[{"id":24,"uname":"王二737"}]
2022-10-31 14:53:29.173  INFO 18800 --- [nio-8080-exec-1] c.q.p.controller.ShardingController      : 数据查询2:[{"id":24,"uname":"王二737"}]

此时可以看到,在一次请求中,执行写入和查询时,操作的都是write数据源,从而规避掉上述提到的数据同步的风险

附录

注意参考官方文档的时候,YAML 配置部分并不是说springboot中的yml配置文件的配置方式,一定要注意!!

参考文档:https://shardingsphere.apache.org/document/5.2.0/cn/user-manual/shardingsphere-jdbc/spring-boot-starter/

猜你喜欢

转载自blog.csdn.net/qq_39198749/article/details/127577547