Sharding-JDBC系列
1、Sharding-JDBC分库分表的基本使用
2、Sharding-JDBC分库分表之SpringBoot分片策略
3、Sharding-JDBC分库分表之SpringBoot主从配置
4、SpringBoot集成Sharding-JDBC-5.3.0分库分表
前言
Apache ShardingSphere,作为全球知名的基础软件开源项目,最早可追溯到 2015 年。其最初版本是当当网内部项目孵化而成,其目的是为了解决数据库水平拆分而产生的分布式问题。在 2016 年正式开源,逐渐得到了更多公司的关注和贡献,项目规模和影响力逐步扩大。在 2018 年, 该项目进入Apache 基金会孵化器,并于 2020 年成为*项目成功孵化。
ShardingSphere 4.x版本是在2019年发布,5.x版本是在2021年发布。在2020年成为Apache基金会*项目之后,特别是到5.3.0,在规范化、性能优化、分片策略等做了很多改动。
《Sharding-JDBC系列》的前3篇博文都是基于Sharding-JDBC-4.1.1,5.x 之后有许多改动,以下以ShardingSphere 5.3.0版本,分享ShardingSphere在SpringBoot中的使用。
准备工作
以下以订单分表为例,介绍Sharding-JDBC 5.3.0的基本使用。
1)订单表:订单表的字段有订单id、会员id、总价格、状态、下单时间;
2)创建两个订单表,分表为tb_order_1和tb_order_2;
3)分表规则:以订单id分表,id被2整除的放tb_order_1,不能被2整除的放tb_order_2;
本篇的示例和Sharding-JDBC分库分表的基本使用-****博客是一样,只是使用的Sharding-JDBC的版本不一样,可以对比着查看。
导入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>Sharding-JDBC-demo2</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core</artifactId>
<version>5.3.0</version>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.33</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
Sharding-JDBC 5.3.0的依赖是shardingsphere-jdbc-core;
在5.x之前,依赖是sharding-jdbc-spring-boot-starter。5.0到5.2,依赖是shardingsphere-jdbc-core-spring-boot-starter;
如果springboot的版本为2.x,会提示org.yaml.snakeyaml.LoaderOptions找不到setCodePointLimit()方法。该类在snakeyaml.jar包,且1.33之后才有这个方法。springboot依赖的snakeyaml为1.30。解决方式如下:
1)方法1:使用springboot 3.x的版本,jdk需要升级到17。idea也要升级为2022之后的版本;
2)方法2:手动引入snakeyaml.jar的1.33版本;
yml配置
从 5.1.2 版本开始,Sharding-JDBC提供了原生JDBC驱动ShardingSphereDriver。在5.3.x之后,配置也做了规范化处理。
4.1 application.yml的配置
server:
port: 8080
spring:
main:
# 处理连接池冲突
allow-bean-definition-overriding: true
datasource:
driver-class-name: org.apache.shardingsphere.driver.ShardingSphereDriver
url: jdbc:shardingsphere:classpath:sharding.yml
在spring.datasource.url中,配置shardingsphere的配置文件路径为sharding.yml
4.2 sharding.yml的配置
dataSources:
order_ds:
dataSourceClassName: com.zaxxer.hikari.HikariDataSource
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/shardingjdbctest?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false
username: root
password: 123456
rules:
- !SHARDING
tables:
tb_order: #逻辑表
actualDataNodes: order_ds.tb_order_$->{1..2} #order1:数据源名称;两个tb_order表,分别为tb_order_1和tb_order_2
keyGenerateStrategy: # 指定主键生成策略
column: order_id
keyGeneratorName: snowflake
tableStrategy:
standard: #没有inline策略
shardingColumn: order_id #分片键。对id进行分表
shardingAlgorithmName: order_inline
shardingAlgorithms: #分片算法
order_inline: #算法名称
type: inline #算法类型
props:
algorithm-expression: tb_order_$->{order_id % 2 + 1} #分片算法
keyGenerators: # 主键生成器
snowflake:
type: SNOWFLAKE
props:
sql-show: true # 是否打印sql
1)独立分片规则的文件,与Spring分离;
2)以驼峰命名取代了下划线命名;
3)在tables规则中,只配置策略及对应算法名称;
4)分片策略中,取消了inline类型的分片策略,只作为标准分片中的inline算法类型;
5)独立分片算法、主键生成器等,当不同的table需要相同的算法时,可以复用;
详细配置查看:YAML 配置 :: ShardingSphere
实体类
package com.jingai.sharing.jdbc.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.ToString;
import java.util.Date;
@Data
@ToString
@TableName("tb_order")
public class OrderEntity {
private long orderId;
private long memberId;
private float totalPrice;
private String status;
private Date orderTime;
}
在实体类中,@TableName指定配置中的逻辑表。
Mapper类
package com.jingai.sharing.jdbc.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jingai.sharing.jdbc.entity.OrderEntity;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Options;
public interface OrderMapper extends BaseMapper<OrderEntity> {
@Insert("insert into tb_order(member_id, total_price, status, order_time) values " +
"(#{memberId}, #{totalPrice}, #{status}, #{orderTime})")
@Options(useGeneratedKeys = true, keyProperty = "orderId")
int insert2(OrderEntity order);
}
在5.2的配置中,通过key-generator设置了逻辑表的主键生成策略为雪花算法。当进行数据插入时,需要编写新的插入接口,不能直接使用Mybatis-plus中的insert()接口。因为在默认的insert()接口中,实体对象的orderId为0,不会走配置的雪花算法。
Service类
package com.jingai.sharing.jdbc.service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jingai.sharing.jdbc.dao.OrderMapper;
import com.jingai.sharing.jdbc.entity.OrderEntity;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class OrderService extends ServiceImpl<OrderMapper, OrderEntity> {
@Resource
private OrderMapper orderMapper;
public long insert2(OrderEntity order) {
int rs = orderMapper.insert2(order);
return rs > 0 ? order.getOrderId() : 0;
}
}
为了便于测试,此处省略了Service的接口类。
Controller类
@RestController
public class OrderController {
@Resource
private OrderService orderService;
@RequestMapping("order")
public String order(OrderEntity order) {
order.setOrderTime(new Date());
long insert = orderService.insert2(order);
return insert > 0 ? "success" : "fail";
}
@RequestMapping("list")
public List<OrderEntity> list() {
return orderService.list();
}
}
8.1 访问order接口
访问order接口,添加记录,打印的日志如下:
id为1018095401464496128,分片到tb_order_1。
8.2 访问list接口
访问list接口,查询全部数据,打印的日志如下:
由于list是查询全部,所以会进行全局扫描查询,需要查询tb_order_1和tb_order_2两个表。此处通过union all,一次性查询了两张表。
对比Sharding-JDBC-4.1.1,对于全局查询,打印的日志如下:
同样是查询tb_order_1和tb_order_2两个表,但是分开两次查询。
小结
以下对比 5.3.0 版本与 4.1.1 的差别:
1)引入的依赖不同,5.3.0 为 shardingsphere-jdbc-core,4.1.1 是sharding-jdbc-spring-boot-starter;
2)配置不同。4.1.1 中的分片策略在application.yml中进行配置,5.3.0 在application.yml中只配置了分片策略的文件路径,分片策略在专门的分片策略文件中配置;
3)5.3.0 相比 4.1.1,提供了许多分片算法。如基于取模的分片算法、基于可变时间范围的分片算法等;
4)5.3.0 相比 4.1.1,某些功能的性能得到了优化;
Shardingsphere文档
YAML 配置 :: ShardingSphere
关于本篇内容你有什么自己的想法或独到见解,欢迎在评论区一起交流探讨下吧。