官方文档:Index of /document 选择自己的版本,我选的5.1.1
1.使用docker-compose创建两个mysql实例
version: '3.8'
services:
mysql8:
image: mysql:8.0.27 #镜像
container_name: server1 #容器名
privileged: true #给予容器额外的权限。这意味着容器将拥有主机系统的所有权限
# restart: always # 服务器启动时,自启动。需要的可以打开
ports:
- "5506:3306" # 9906是宿主机端口,3306是容器内部接口
volumes: # 文件挂载,与容器内部的文件做挂载
- ./data:/var/lib/mysql
- ./config:/etc/mysql/conf.d
- ./logs:/var/logs
environment: #环境变量
- MYSQL_ROOT_PASSWORD=123456 # 设置 ROOT 用户登录密码
- TZ=Asia/Shanghai #设置 MySQL 的时区
version: '3.8'
services:
mysql8:
image: mysql:8.0.27 #镜像
container_name: server2 #容器名
privileged: true #给予容器额外的权限。这意味着容器将拥有主机系统的所有权限
# restart: always # 服务器启动时,自启动。需要的可以打开
ports:
- "5507:3306" # 9906是宿主机端口,3306是容器内部接口
volumes: # 文件挂载,与容器内部的文件做挂载
- ./data:/var/lib/mysql
- ./config:/etc/mysql/conf.d
- ./logs:/var/logs
environment: #环境变量
- MYSQL_ROOT_PASSWORD=123456 # 设置 ROOT 用户登录密码
- TZ=Asia/Shanghai #设置 MySQL 的时区
2.创建数据库和表
进入容器server0和server1,这里以server0为例,server1是一样的步骤
docker exec -it server0 bash
进入mysql创建数据库和表
mysql -uroot -p123456
create database test;
use test;
create table t_order0 (
id BIGINT,
user_id BIGINT,
price DECIMAL(10,2),
PRIMARY KEY(id)
);
create table t_order1 (
id BIGINT,
user_id BIGINT,
price DECIMAL(10,2),
PRIMARY KEY(id)
);
3.引入依赖
<dependencies>
<!--测试相关依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.19</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<version>2.5.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--sharding依赖-->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
<version>5.1.1</version>
</dependency>
<!-- Mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.23</version>
<scope>runtime</scope>
</dependency>
</dependencies>
4.实体类
public class Order {
private long id;
private long userId;
private BigDecimal price;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public long getUserId() {
return userId;
}
public void setUserId(long userId) {
this.userId = userId;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
@Override
public String toString() {
return "Order{" +
"id=" + id +
", userId=" + userId +
", price=" + price +
'}';
}
}
5.mapper
public interface OrderMapper {
@Insert("INSERT INTO t_order (id,user_id,price) values (#{id},#{userId},#{price})")
int insert(Order record);
@Results({
@Result(column = "user_id", property = "userId")
})
@Select("SELECT * from t_order")
List<Order> selectAll();
}
6.配置文件
spring:
shardingsphere:
mode:
type: Memory # 有集群,单机,内存。自己学习用内存模式即可
datasource:
names: server0,server1 #每个数据源的名称
server0:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.6.128:5506/test?allowPublicKeyRetrieval=true
username: root
password: 123456
server1:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.6.128:5507/test?allowPublicKeyRetrieval=true
username: root
password: 123456
rules:
sharding:
tables:
# 需要分库的表名
t_order:
# 由数据源名 + 表名组成,以小数点分隔。多个表以逗号分隔,支持 inline 表达式。缺省表示使用已知数据源与逻辑表名称生成数据节点,用于广播表(即每个库中都需要一个同样的表用于关联查询,多为字典表)或只分库不分表且所有库的表结构完全一致的情况
actual-data-nodes:
server$->{0..1}.t_order$->{0..1}
# 分库策略
database-strategy:
# 单分片键 (根据一个字段去分),多分片键就是多个字段
standard:
# 分片列名称
sharding-column: id
# 分片算法名称 (自定义名称即可)
sharding-algorithm-name: mod
# 分表策略
table-strategy:
# 单分片键
standard:
# 分片列名称
sharding-column: user_id
# 分片算法名称 (自定义名称即可)
sharding-algorithm-name: mod
# 分片算法配置
sharding-algorithms:
# 上面自定义的算法名称
mod:
# 类型为取模算法,文档里有多种算法,可以自己去看
type: MOD
#因为我们有两个库,所以写2
props:
sharding-count: 2
props:
sql-show: true # 显示Sql
7.测试类
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Sharding.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) //classes是主类的启动名称
public class MyTest {
@Autowired
OrderMapper orderMapper;
@Test
public void save() {
for (int i = 0; i < 4; i++) {
Order order = new Order();
order.setId(i);
order.setUserId(1);
order.setPrice(BigDecimal.valueOf(3.3));
orderMapper.insert(order);
}
for (int i = 0; i < 4; i++) {
Order order = new Order();
order.setId(i);
order.setUserId(2);
order.setPrice(BigDecimal.valueOf(3.3));
orderMapper.insert(order);
}
}
@Test
public void selectOrderAll() {
List<Order> orders = orderMapper.selectAll();
orders.forEach(System.out::println);
}
}
运行save方法,可以看到,两个库的两张表都插入了两条数据。
数据库里也是有的。
运行selectOrderAll方法,我们发现,shardingSphere自动帮我们连表,然后再返回数据。
8.主键雪花ID策略
在上面我们发现,不同的表中,生成的id会有重复,这对于分布式不是很好,我们选用shardingSphere中的雪花id策略,来让每个表中的id不重复且是递增的。
8.1修改mapper文件
把id去掉,让shardingSphere帮我们生成
public interface OrderMapper {
@Insert("INSERT INTO t_order (user_id,price) values (#{userId},#{price})")
int insert(Order record);
@Results({
@Result(column = "user_id", property = "userId")
})
@Select("SELECT * from t_order")
List<Order> selectAll();
}
8.2修改配置文件
添加分布式序列策略配置和
# 分布式序列算法配置
完整配置文件
spring:
shardingsphere:
mode:
type: Memory # 有集群,单机,内存。自己学习用内存模式即可
datasource:
names: server0,server1 #每个数据源的名称
server0:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.6.128:5506/test?allowPublicKeyRetrieval=true
username: root
password: 123456
server1:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.6.128:5507/test?allowPublicKeyRetrieval=true
username: root
password: 123456
rules:
sharding:
tables:
# 需要分库的表名
t_order:
# 由数据源名 + 表名组成,以小数点分隔。多个表以逗号分隔,支持 inline 表达式。缺省表示使用已知数据源与逻辑表名称生成数据节点,用于广播表(即每个库中都需要一个同样的表用于关联查询,多为字典表)或只分库不分表且所有库的表结构完全一致的情况
actual-data-nodes:
server$->{0..1}.t_order$->{0..1}
# 分库策略
database-strategy:
# 单分片键 (根据一个字段去分),多分片键就是多个字段
standard:
# 分片列名称
sharding-column: id
# 分片算法名称 (自定义名称即可)
sharding-algorithm-name: mod
# 分表策略
table-strategy:
# 单分片键
standard:
# 分片列名称
sharding-column: user_id
# 分片算法名称 (自定义名称即可)
sharding-algorithm-name: mod
# 分布式序列策略配置
key-generate-strategy:
# 列名
column: id
# 自定义算法名
key-generator-name: snowflake
# 分片算法配置
sharding-algorithms:
# 上面自定义的算法名称
mod:
# 类型为取模算法,文档里有多种算法,可以自己去看
type: MOD
#因为我们有两个库,所以写2
props:
sharding-count: 2
# 分布式序列算法配置
key-generators:
# 和分布式序列策略配置自定义名一致
snowflake:
# 算法类型,我们选择雪花
type: SNOWFLAKE
props:
sql-show: true # 显示Sql
8.3修改测试类
设置id的那行代码去掉即可。
@Test
public void save() {
for (int i = 0; i < 4; i++) {
Order order = new Order();
order.setUserId(1);
order.setPrice(BigDecimal.valueOf(3.3));
orderMapper.insert(order);
}
for (int i = 0; i < 4; i++) {
Order order = new Order();
order.setUserId(2);
order.setPrice(BigDecimal.valueOf(3.3));
orderMapper.insert(order);
}
}
运行完查看日志,发现shardingSphere帮我们生成了id。
查看数据库