完整代码已上传 [Gitee Spring整合常用组件](https://cloud.tencent.com/developer/tools/blog-entry?target=https://gitee.com/creyanghang/spring-example/tree/master/spring-shardingsphere)
前提条件
MySQL主从同步已搭建完成。参考链接
相关DDL:
代码语言:javascript复制CREATE DATABASE db_user;
USE db_user;
CREATE TABLE t_user (
id BIGINT AUTO_INCREMENT,
uname VARCHAR(30),
PRIMARY KEY (id)
);
INSERT INTO t_user(uname) VALUES('zhang3');
INSERT INTO t_user(uname) VALUES(@@hostname);
复制
1、创建SpringBoot程序
1.1、创建项目
项目名:sharding-jdbc-demo
SpringBoot版本:2.5.9
1.2、添加依赖
代码语言:javascript复制<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
<version>5.1.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
复制
1.3、创建实体类
代码语言:javascript复制package org.example.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* @description: PO实体类
* @author: yh
* @date: 2022/9/18
*/
@TableName("t_user")
@Data
public class User {
@TableId(type = IdType.AUTO)
private Long id;
private String uname;
}
复制
1.4、创建Mapper
代码语言:javascript复制@Mapper
public interface UserMapper extends BaseMapper<User> {
}
复制
1.5、Controller
代码语言:javascript复制@RestController
@RequestMapping(value = "/user")
public class UserController {
@Resource
private UserMapper userMapper;
/**
* 插入数据,测试是否写入master
* 如果开启事务,读会走master数据源
* @author: yh
* @date: 2022/9/18
*/
// @Transactional
@GetMapping("/insert")
public void userInsert(){
User u = new User();
u.setUname("西门庆" System.currentTimeMillis());
userMapper.insert(u);
// List<User> users = userMapper.selectList(null);
// System.out.println(users.size());
}
/**
* 查询
* @author: yh
* @date: 2022/9/18
*/
@GetMapping("/selectAll")
public void selectAll(){
userMapper.selectList(null);
}
}
复制
1.6、配置读写分离
application.yml:
代码语言:javascript复制spring:
application:
name: sharging-jdbc-demo
profiles:
active: dev
复制
application-dev.yml:
代码语言:javascript复制# 读写分离配置
spring:
shardingsphere:
datasource:
# 配置真实数据源
names: master,slave1,slave2
# 配置第 1 个数据源
master:
driver-class-name: com.mysql.jdbc.Driver
jdbc-url: jdbc:mysql://192.168.1.1:3306/db_user
password: 123456
type: com.zaxxer.hikari.HikariDataSource
username: root
# 配置第 2 个数据源
slave1:
driver-class-name: com.mysql.jdbc.Driver
jdbc-url: jdbc:mysql://192.168.1.1:3307/db_user
password: 123456
type: com.zaxxer.hikari.HikariDataSource
username: root
# 配置第 3 个数据源
slave2:
driver-class-name: com.mysql.jdbc.Driver
jdbc-url: jdbc:mysql://192.168.1.1:3308/db_user
password: 123456
type: com.zaxxer.hikari.HikariDataSource
username: root
mode:
# 内存模式
type: Memory
# 打印sql
props:
sql-show: true
rules:
readwrite-splitting:
data-sources:
myds:
# 读数据源负载均衡算法名称
load-balancer-name: alg_round
props:
# 读数据源名称,多个从数据源用逗号分隔
read-data-source-names: slave1,slave2
# 写数据源名称
write-data-source-name: master
# 读写分离类型,如: Static,Dynamic
type: Static
load-balancers:
# 定义负载均衡算法:随机,轮询,权重
alg_random:
type: RANDOM
alg_round:
type: ROUND_ROBIN
alg_weight:
props:
slave1: 1
slave2: 2
type: WEIGHT
复制
2、测试
2.1、读写分离测试
启动App Server,请求http://127.0.0.1:8080/user/insert
在这里插入图片描述
写入主数据源后,查询主数据库中数据是否写入,从数据库数据是否正常同步
2.2、事务测试
为了保证主从库间的事务一致性,避免跨服务的分布式事务,ShardingSphere-JDBC的主从模型中,事务中的数据读写均用主库
。
- 不添加
@Transactional
:insert
对主库操作,select
对从库操作 - 添加
@Transactional
:则insert
和select
均对主库操作 - 注意: 如果在JUnit环境下的
@Transactional
注解,默认情况下就会对事务进行回滚(即使在没加注解@Rollback
,也会对事务回滚)
@Transactional
@GetMapping("/insert")
public void userInsert(){
User u = new User();
u.setUname("西门庆" System.currentTimeMillis());
userMapper.insert(u);
List<User> users = userMapper.selectList(null);
System.out.println(users.size());
}
复制
在这里插入图片描述
2.3、负载均衡测试
代码语言:javascript复制load-balancer-name: alg_round # 轮询
复制
在这里插入图片描述
查询6次结果:slave1,slave2,slave1,slave2,slave1,slave2。结果轮询
代码语言:javascript复制load-balancer-name: alg_weight # 权重
复制
在这里插入图片描述
访问9次:slave1数据库3次,slave2数据库6次。权重 1:2
代码语言:javascript复制load-balancer-name: alg_random # 随机
复制
访问6次:slave2,slave2,slave1,slave2,slave2,slave1,slave1。结果随机