上篇博客,我们讲了 ShardingSphere实战(1)- 分库分表基础知识,这篇博客,正式开始实操。
项目环境:
JDK11
MySQL 8.0.30
Springboot 2.7.4 + Mybatis + ShardingSphere + HikariCP 连接池
一、Maven 依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.4</version>
</parent>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>33.2.1-jre</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- ShardingSphere -->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.1.1</version>
</dependency>
<!--HikariCP 高性能的JDBC连接池-->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.0.0</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
</dependencies>
二、创建数据库
create database ds-0;
create table t_order_0
(
order_id bigint not null
primary key,
order_no varchar(100) null,
create_name varchar(50) null,
price decimal(10, 2) null
)
create table t_order_1
(
order_id bigint not null
primary key,
order_no varchar(100) null,
create_name varchar(50) null,
price decimal(10, 2) null
)
create table t_order_item_0
(
order_item_id bigint not null
primary key,
item_id bigint null,
order_id bigint null,
item_name varchar(50) null,
price decimal(10, 2) null
)
create table t_order_item_1
(
order_item_id bigint not null
primary key,
item_id bigint null,
order_id bigint null,
item_name varchar(50) null,
price decimal(10, 2) null
)
三、项目搭建
package com.shardingsphere.demo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@SpringBootApplication
@MapperScan({"com.shardingsphere.demo.dal.mapper"})
public class ShardingsphereDemoApplication {
public static void main(String[] args) {
SpringApplication.run(ShardingsphereDemoApplication.class, args);
}
@RequestMapping
public String health() {
return "shardingsphere-demo is ok!";
}
}
实体类以及 mapper 的具体代码就不贴了,就是一个简单的 springboot + mybatis 项目。
四、单个表配置 ShardingSphere 分片策略
# sharding-jdbc 水平分表策略
# 给数据源起别名,这里名称需要和下面的一致
spring.shardingsphere.datasource.names=ds-0
# 配置数据源
spring.shardingsphere.datasource.ds-0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds-0.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds-0.jdbc-url=jdbc:mysql://xxx:3306/ds-0?serverTimezone=UTC&useSSL=false
spring.shardingsphere.datasource.ds-0.username=xxx
spring.shardingsphere.datasource.ds-0.password=xxx
####################### 配置分片表t_order #######################
# 指定真实数据节点
spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=ds-0.t_order_$->{0..1}
### 分表策略
# 分表分片健
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.sharding-column=order_id
# 分表算法
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.algorithm-expression=t_order_$->{order_id % 2}
# 是否开启 SQL解析日志
spring.shardingsphere.props.sql.show=true
mybatis.mapper-locations=classpath:sqlmapper/*.xml
1. 插入数据
/**
* 单个表水平分表测试-保存
*/
@GetMapping("/test1")
public String test1(@RequestParam("count") Integer count) {
for (int i = 0; i < count; i++) {
OrderDO order = new OrderDO();
order.setOrderId(this.getId());
order.setOrderNo("A" + order.getOrderId());
order.setCreateName("订单 " + order.getOrderId());
orderMapper.insertSelective(order);
}
return "success";
}
运行代码,可以看到 order_id
为偶数进了 t_order_0
,为奇数进了t_order_1
,和我们配置的分片规则一致。
2. 查询数据
/**
* 单个表水平分表测试-查询
*/
@GetMapping("/test2")
public String test2(@RequestParam("orderId") Long orderId) {
OrderDO orderDO = orderMapper.selectByPrimaryKey(orderId);
log.info("orderDO: {}", orderDO.toString());
return "success";
}
运行代码,可以看到 order_id
为偶数查询 t_order_0
,为奇数查询t_order_1
,和我们配置的分片规则一致。
到目前为止,一个最简单的分表 demo 就完成了。
五、多个表配置 ShardingSphere 分片策略
如果我们还有一张t_order_item
表,也需要分表,并且同样需要按照order_id
分片
在上面配置的基础上,加上下面的配置:
####################### 配置分片表t_order_item #######################
# 指定真实数据节点
spring.shardingsphere.sharding.tables.t_order_item.actual-data-nodes=ds-0.t_order_item_$->{0..1}
### 分表策略
# 分表分片健
spring.shardingsphere.sharding.tables.t_order_item.table-strategy.inline.sharding-column=order_id
# 分表算法
spring.shardingsphere.sharding.tables.t_order_item.table-strategy.inline.algorithm-expression=t_order_item_$->{order_id % 2}
1. 插入数据
/**
* 多个表水平分表测试-保存
*/
@GetMapping("/test3")
public String test3(@RequestParam("count") Integer count) {
for (int i = 0; i < count; i++) {
OrderDO order = new OrderDO();
order.setOrderId(this.getId());
order.setOrderNo("A" + order.getOrderId());
order.setCreateName("订单 " + order.getOrderId());
orderMapper.insertSelective(order);
OrderItemDO orderItem = new OrderItemDO();
orderItem.setOrderItemId(order.getOrderId());
orderItem.setOrderId(order.getOrderId());
orderItemMapper.insertSelective(orderItem);
}
return "success";
}
运行结果就不看了,和上面一致,按照order_id
分片
2. 查询数据
/**
* 多个表水平分表测试-查询
*/
@GetMapping("/test4")
public String test4(@RequestParam("orderId") Long orderId) {
List<OrderItemExtDO> orderDO = orderMapper.findOrderAndOrderItemsByOrderId(orderId);
log.info("orderDO: {}", orderDO.toString());
return "success";
}
<select id="findOrderAndOrderItemsByOrderId" resultType="com.shardingsphere.demo.dal.entity.OrderItemExtDO">
select t1.order_id t1OrderId,
t1.order_no orderNo,
t2.order_id t2OrderId
from t_order t1
inner join t_order_item t2 on t1.order_id = t2.order_id
where t1.order_id = #{orderId,jdbcType=BIGINT}
</select>
和单表不一样,这次是t_order
和t_order_item
表关联查询,观察结果:
可以看到,sql 执行了两次,也就是说取的是笛卡尔积,可以想象,如果我们分表数量多,查询效率肯定极低,所以针对这种情况,我们需要配置绑定表
六、完整配置
为了方便查看,下面放一个本篇博客关于ShardingSphere
的完整配置:
# sharding-jdbc 水平分表策略
# 给数据源起别名,这里名称需要和下面的一致
spring.shardingsphere.datasource.names=ds-0
# 配置数据源
spring.shardingsphere.datasource.ds-0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds-0.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds-0.jdbc-url=jdbc:mysql://xxx:3316/ds-0?serverTimezone=UTC&useSSL=false
spring.shardingsphere.datasource.ds-0.username=xxx
spring.shardingsphere.datasource.ds-0.password=xxx
####################### 配置分片表t_order #######################
# 指定真实数据节点
spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=ds-0.t_order_$->{0..1}
### 分表策略
# 分表分片健
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.sharding-column=order_id
# 分表算法
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.algorithm-expression=t_order_$->{order_id % 2}
####################### 配置分片表t_order_item #######################
# 指定真实数据节点
spring.shardingsphere.sharding.tables.t_order_item.actual-data-nodes=ds-0.t_order_item_$->{0..1}
### 分表策略
# 分表分片健
spring.shardingsphere.sharding.tables.t_order_item.table-strategy.inline.sharding-column=order_id
# 分表算法
spring.shardingsphere.sharding.tables.t_order_item.table-strategy.inline.algorithm-expression=t_order_item_$->{order_id % 2}
# 是否开启 SQL解析日志
spring.shardingsphere.props.sql.show=true
mybatis.mapper-locations=classpath:sqlmapper/*.xml
总结:本篇博客实现了水平分表
,后续会陆续更新分库分表
、绑定表
、广播表
等
下一篇:ShardingSphere实战(3)- 快速实现分库分表