博主负责的IOT PC 租赁项目由于在设计阶段,因产品说不需要支持多租户的模式,所以在代码设计中,没有考虑这方面,突然前段时间,gou产品说需要做此模式。于是又要进行预研工作。
设计思路本来想法,是通过数据表字段的方式作为数据伪隔离(所有操作,都增加字段条件),这样的话,可以减少代码修改,但是又考虑到该项目架构较为简单,数据存储方面只用到了mysql和redis, 没有用时序数据库,或mongodb用来存业务数,mysql中存在部分大数据表,如果单单使用字段进行隔离,会造成查询效率问题,so,打算用shardingjdbc对大表进行分表(当然也可以分库,但是个人认为这里没必要),接下来就是代码文件演示。
代码 pom下面pom引包。
yml配置(重点)org.apache.shardingsphere shardingsphere-jdbc-core-spring-boot-starter 5.0.0-beta
下面是关于shardingsphere和jpa的配置,分布式看各自所需,因为是预研,所以没有涉及这段。jpa配置的是自动生成表和库。
spring:
shardingsphere:
# 数据源配置
datasource:
# 数据源名称,多数据源以逗号分隔
names: zc #
zc:
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
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: root
# 规则配置
rules:
sharding:
tables:
# 逻辑表名称
device_log:
# 行表达式标识符可以使用 ${...} 或 $->{...},但前者与 Spring 本身的属性文件占位符冲突,因此在 Spring 环境中使用行表达式标识符建议使用 $->{...}
actual-data-nodes: zc.device_log_$->{1..3}
# 分表策略
table-strategy:
standard:
# 分片列名称
sharding-column: company_code
# 分片算法名称
sharding-algorithm-name: table-inline
# 表主键算法
# key-generate-strategy:
# column: id
# key-generator-name: snowflake
# 分片算法配置
sharding-algorithms:
table-inline:
# 分片算法类型
type: INLINE
props:
# 分片算法的行表达式
algorithm-expression: device_log_$->{company_code}
# # 分布式序列算法配置
# key-generators:
# snowflake:
# # 分布式序列算法(雪花算法:SNOWFLAKE; UUID:UUID)
# type: SNOWFLAKE
# # 分布式序列算法属性配置
# props:
# # 工作机器唯一标识
# worker-id: 123
jpa:
database: mysql
database-platform: org.hibernate.dialect.MySQL57Dialect
hibernate:
ddl-auto: update
properties:
hibernate:
jdbc:
time_zone: UTC
messages:
encoding: UTF-8
测试代码
下面展示测试代码。插入的时候会根据配置的code进行分表插入,findAll 也会查询所有表,但是本机测试有点慢,应该要避免这种操作,根据code查询数据,也是会查询对应的分表。
ListmerchantList = 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 deviceLogs = deviceLogRepository.findAll(); // 根据code查询数据 List 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 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版本点的不同,配置文件也会不同,需要按版本修改配置。



