前言
ShardingSphere基础知识、ShardingSphere-JDBC如何集成进若依框架中
使用的是若依框架(SpringBoot)前后端版本、动态数据源,可自行切换,默认数据源为达梦8
文章目录
- 前言
- 基础知识
- 简介
- 产品功能
- 使用
- 方案一
- 方案二
- 方案三
- 注意点
- 参考内容
基础知识
官网文档地址:https://shardingsphere.apache.org/document/current/cn/overview/
简介
- 开源的分布式数据库中间件解决方案组成的生态圈
- 关系型数据库中间件
- 产品组件
- ShardingSphere-JDBC:轻量级Java框架,在Java的JDBC层提供额外服务
- ShardingSphere-Proxy:透明化的数据库代理端,通过实现数据库二进制协议,对异构语言提供支持
产品功能
- 数据分片:分库、分表(垂直、水平)
- 分布式事务
- 读写分离
- 数据迁移
- 联邦查询:跨数据源查询
- 数据加密
- 影子库:压测数据隔离的影子数据库
使用
项目框架:若依前后端分离版本(SpringBoot 2.7.10)
ORM:Mybatis Plus(mybatis-plus-boot-starter 3.5.3)
数据库连接池:druid(druid-spring-boot-starter 1.2.15)
组件:ShardingSphere-JDBC(shardingsphere-jdbc-core-spring-boot-starter 5.2.0)
方案一
-
总pom引入shardingsphere-jdbc-core-spring-boot-starter
<!-- 分库分表引擎 --> <dependency><groupId>org.apache.shardingsphere</groupId><artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId><version>5.2.0</version> </dependency>
-
framework模块引入shardingsphere-jdbc-core-spring-boot-starter
-
admin模块新增配置文件application-shardingsphere.yml
# 数据源配置 spring:shardingsphere:# 单机模式mode:type: Standaloneprops:sql-show: true# 数据源配置datasource:names: druid,sharding# 主库数据源master:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: dm.jdbc.driver.DmDriverurl: jdbc:dm://localhost:5236?SCHEMA=xx&zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&rewriteBatchedStatements=trueusername: SYSDBApassword: SYSDBA# 分库数据源 sharding:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: dm.jdbc.driver.DmDriverurl: jdbc:dm://localhost:5236?SCHEMA=xxusername: SYSDBApassword: SYSDBA # driver-class-name: com.mysql.jdbc.Driver # url: jdbc:mysql://localhost:3306/ry-order1?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 # username: root # password: root # 标准分片配置rules:# 分片规则sharding:tables:# 表名tb_user:actual-data-nodes: sharding.tb_user_${0..1} # 相当于tb_user_0、tb_user_1table-strategy: # 分表策略standard: # 标准分表策略sharding-column: id # 分表列名sharding-algorithm-name: tb_user_inline # 分表算法名字# 分片算法shardingAlgorithms:tb_user_inline:# 策略类型type: INLINEprops:algorithm-expression: tb_user_$->{id % 2} # 结果为0和1,与上面的表名对应
-
相应修改DruidProperties.java里的配置值
结果:没有数据分片的效果
方案二
在方案一的基础上
-
DataSourceType加上类型SHARDING
-
DruidConfig加上数据源
setDataSource(targetDataSources, DataSourceType.SHARDING.name(), "shardingSphereDataSource");
-
调用方法上增加数据源类型
@Override @DataSource(DataSourceType.SHARDING) public Long insertNew(User user) {return (long) userMapper.insert(user); }
注意点:shardingSphereDataSource默认使用的数据源名称就是sharding
结果:可以进行数据分片
方案三
-
总pom引入shardingsphere-jdbc-core-spring-boot-starter
<!-- 分库分表引擎 --> <dependency><groupId>org.apache.shardingsphere</groupId><artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId><version>5.2.0</version> </dependency>
-
framework模块引入shardingsphere-jdbc-core-spring-boot-starter
-
admin模块配置文件新增配置项指定sharding配置
spring:shardingsphere:configLocation: application-sharding.yml
-
新增sharding配置文件application-sharding.yml,注意部分单词驼峰
# 数据源 dataSources:sharding:dataSourceClassName: com.alibaba.druid.pool.DruidDataSourcedriverClassName: dm.jdbc.driver.DmDriverurl: jdbc:dm://localhost:5236?SCHEMA=xxusername: SYSDBApassword: SYSDBAmaxTotal: 100 # ds_1: # dataSourceClassName: com.alibaba.druid.pool.DruidDataSource # driverClassName: com.mysql.cj.jdbc.Driver # url: jdbc:mysql://localhost:3306/ry-order2?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 # username: root # password: root # maxTotal: 100rules:- !TRANSACTIONdefaultType: LOCAL- !SHARDINGtables:# 表名tb_user:actualDataNodes: sharding.tb_user_$->{0..1}tableStrategy: # 分表策略standard: # 标准分表策略sharding-column: id # 分表列名sharding-algorithm-name: tb_user_inline # 分表算法名字# 分片算法shardingAlgorithms:tb_user_inline:# 策略类型type: INLINEprops:algorithm-expression: tb_user_$->{id % 2}# 分布式序列算法配置(主键生成)keyGenerators:# 雪花算法snowflake:type: SNOWFLAKEprops:# 输出SQLsql-show: true
-
新增sharding配置类:ShardingProperties.java
import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration;@Configuration public class ShardingProperties {@Value("${spring.shardingsphere.configLocation}")private String configLocation;public String getConfigLocation() {return configLocation;} }
-
DataSourceType加上类型SHARDING
-
DruidConfig加上数据源
@Bean public DataSource shardingDataSource(ShardingProperties shardingProperties) throws Exception{ClassPathResource classPathResource = new ClassPathResource(shardingProperties.getConfigLocation());InputStream inputStream = classPathResource.getInputStream();File tmpFile = File.createTempFile(shardingProperties.getConfigLocation(), ".tmp");Files.copy(inputStream, tmpFile.toPath(), StandardCopyOption.REPLACE_EXISTING);DataSource dataSource = YamlShardingSphereDataSourceFactory.createDataSource(tmpFile);return dataSource;}// 动态数据源方法加上sharding @Bean(name = "dynamicDataSource") @Primary public DynamicDataSource dataSource(DataSource masterDataSource) {Map<Object, Object> targetDataSources = new HashMap<>();targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource);setDataSource(targetDataSources, DataSourceType.SHARDING.name(), "shardingDataSource");return new DynamicDataSource(masterDataSource, targetDataSources);}
-
调用方法上增加数据源类型
结果:可以进行数据分片
注意点
-
ShardingSphere各个版本有差异,并且不一定完全向前兼容,与其他框架如Springboot、druid上可能也存在某些版本无法兼容,所以需要注意引入的各个框架的版本
-
只有使用分片键进行操作才会通过分表扫描,否则依然是全表扫描
-
不支持分片表和单表关联查询
- 解决方案:重写sql,不走分片查询
-
分页:如果是一些非主流的数据库,不在支持的数据库类型里,则需要适配
-
解决方案一:使用支持的数据库方言类型,如MySQL
-
解决方案二:通过自定义分页SQL实现
SELECT * FROM ( SELECT TMP.*, ROWNUM ROW_ID FROM ( SELECT id, company_code, FROM table_name ) TMP WHERE ROWNUM <=?) WHERE ROW_ID > ?
-
-
无法更新:IService.updateById()
- 不能更新分片键字段,因为可能存在更新完不在此分片表里
- 实体表字段加注解不更新:
@TableField(updateStrategy = FieldStrategy.NEVER)
-
表约束失效:唯一性约束在多个表失效
-
使用in条件,即使使用分片键,还是会走全路由
参考内容
- 自定义分片算法:参考1、参考2、参考3