基于springboot+sharding jdbc +spring data jpa进行分表
背景
博主负责的IOT PC 租赁项目由于在设计阶段,因产品说不需要支持多租户的模式,所以在代码设计中,没有考虑这方面,突然前段时间,gou产品说需要做此模式。于是又要进行预研工作。
设计思路
本来想法,是通过数据表字段的方式作为数据伪隔离(所有操作,都增加字段条件),这样的话,可以减少代码修改,但是又考虑到该项目架构较为简单,数据存储方面只用到了mysql和redis, 没有用时序数据库,或mongodb用来存业务数,mysql中存在部分大数据表,如果单单使用字段进行隔离,会造成查询效率问题,so,打算用shardingjdbc对大表进行分表(当然也可以分库,但是个人认为这里没必要),接下来就是代码文件演示。
代码
pom
下面pom引包。
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
<version>5.0.0-beta</version>
</dependency>
yml配置(重点)
下面是关于shardingsphere和jpa的配置,分布式看各自所需,因为是预研,所以没有涉及这段。jpa配置的是自动生成表和库。
spring:
main:
allow-bean-definition-overriding: true
application:
name: secure-pc-device-server-duozuhu
jackson:
default-property-inclusion: non_null
cloud:
nacos:
discovery:
server-addr: nacos:8848
config:
server-addr: nacos:8848
file-extension: yaml
# 配置真实数据源
# 配置真实数据源
shardingsphere:
# 数据源配置
datasource:
names: zc
zc:
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
jdbc-url: jdbc:mysql://localhost:3306/zc?createDatabaseIfNotExist=true&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useLegacyDatetimeCode=false&serverTimezone=UTC
username: root
password: root
rules:
sharding:
sharding-algorithms:
table-inline:
type: INLINE
props:
algorithm-expression: device_log_$->{company_code}
device-inline:
type: INLINE
props:
algorithm-expression: device_$->{company_code}
key-generators:
snowflake:
type: SNOWFLAKE
props:
worker-id: 1
tables:
device_log:
actual-data-nodes: zc.device_log_$->{1..3}
table-strategy:
standard:
sharding-column: company_code
sharding-algorithm-name: table-inline
device:
actual-data-nodes: zc.device_$->{1..3}
table-strategy:
standard:
sharding-column: company_code
sharding-algorithm-name: device-inline
注意:
tables.**.table-strategy.standard.sharding-algorithm-name的内容要和rules.sharding.sharding-algorithms.name.**中的name内容对应上。
测试代码
下面展示测试代码。插入的时候会根据配置的code进行分表插入,findAll 也会查询所有表,但是本机测试有点慢,应该要避免这种操作,根据code查询数据,也是会查询对应的分表。
List<String> merchantList = Lists.newArrayList("1", "2", "3");
// 插入20条数据
for (int i = 0; i < 20; i++) {
DeviceLog log = new DeviceLog();
log.setSn("9999" + i);
log.setCompanyCode(merchantList.get(new Random().nextInt(merchantList.size())));
log.setCreateTime(DateUtils.format(new Date(), DateUtil.pattern_yMdHms));
log.setTmxData("{}");
log.setShanzuData("{}");
deviceLogRepository.save(log);
}
// 查询所有数据
List<DeviceLog> deviceLogs = deviceLogRepository.findAll();
// 根据code查询数据
List<DeviceLog> deviceLogs1 = deviceLogRepository.queryDeviceLogByCode(merchantList.get(new Random().nextInt(merchantList.size())));
queryDeviceLogByCode的sql:
@Query(value = "select * from device_log c where c.company_code = :companyCode",nativeQuery = true)
List<DeviceLog> queryDeviceLogByCode(@Param("companyCode") String companyCode);
预研过程中遇到的坑
1.刚开始sharding版本过低,3.x和4.x都会遇到Unsupported Date type:class java.lang.String错误,升级到5.0.0-beta版本,至于其他文章说的什么关闭日志sql打印,完全就是扯淡。
具体issue:https://github.com/apache/shardingsphere/issues/12822
2.由于sharding版本点的不同,配置文件也会不同,需要按版本修改配置。
sharding的优缺点
优点:配置简单,对业务代码无入侵,无需其他的第三方服务器等。
缺点:需要手动创建数据库表。。。。。。。。。。。。。。。。。。。。