ShardingSphere :
1、一套开源的分部署数据库中间件解决方案
2、有三个产品组成:Sharding-JDBC 、 Sharding-Proxy 和 Sharding-Sidecar(规划中)
3、定位为关系型数据库中间件,合理在分布式环境下使用关系型数据库
什么是分库分表:
1、数据库数据量是不可控的,随着时间和业务的发展,造成表里面数据越来越多,如果再去对表进行CRUD操作的时候,会造成性能的问题
方案1:从硬件上解决,加内存,加cpu,加硬盘(成本过高)
方案2:分库分表 * 为了解决由于数据量过大而造成数据库性能降低的问题
分库分表的方式:
1、垂直切分:
①垂直分表概念:(把单个表 拆分成两张表进行查询)
(1)操作数据库中的某张表,把这张表中的一部分字段数据存到另一张表中,再把这张表中的另一部分的字段的数据存到另外一张表中
例如 订单当中有些商品名称存储在 商品配置信息表中, 订单的信息存储在订单表中
②垂直分库:(把单一数据库按照业务进行划分,专库专表的操作)
(1)按照每个业务,每个业务都需要建一个数据库,专门用于处理业务的数据
例如 订单 与 商品分表建议一个库来存储
小缺点:如果单个业务 数据量过大的话,那么单用垂直分库分表的话那么还是会造成系统性能降低
2、水平切分:
①水平分库:(将一模一样的数据库结构分为多个库存储)
操作方式 例如 判断课程Id为奇数的时候存进数据库A 课程Id为偶数的时候存进数据库B 根据业务可自行写算法进行塞值
例如 数据库A 数据库B 里面同样存储订单表当中数据 而表结构是一模一样的
单用缺陷:库中数据量达到一定数量得增加服务器或者另外的数据库 成本过高
②水平分表:(在同一个数据库中,同样表结构,以不同后缀区分表名进行拆分)
操作方式 例如在同一个数据库内, 表A 与 表B 结构一致,表名以年月区分 A_202101 A_202102
垂直:改变结构 水平:改变数据量
分库分表的应用与问题:
1、应用:
(1)在数据库设计阶段就需要考虑垂直分库和垂直分表
(2)随着数据库数据量的增加,不要马上考虑首先进行水平切分,首先考虑进行缓存、读写分离、使用索引等方法,如果这些方法都没办法解决的话,那么再考虑水平分库与分表
2、分库分表问题:
(1)跨节点连接查询 (分页、排序)
例如 数据库A 和数据库B 进行垂直划分 两个在不同的数据库中,现在想查询 数据库A 与数据库B中 包含的数据 需要进行汇总等操作,数据库操作次数过多
(2)多数据源管理问题
ShardingSphere-JDBC (并不是做分库分表,是用于数据分片和主从复制)
简介:
1、是一个轻量级的java框架,是个增强版的jdbc
2、主要的目的是:简化对分库分表之后数据的相关操作
ShardingSphere-JDBC 实现水平分表:
1、引入Sharding-JDBC连接池 相关依赖
<!--sharding-sphere-jdbc-->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.1.1</version>
</dependency>
2、创建相关数据库与表
3、约定相关匹配规则(举例-id为奇数或者偶数)或者日期
4、添加相关配置(根据文档进行配置)
https://shardingsphere.apache.org/document/current/cn/user-manual/shardingsphere-jdbc/yaml-config/
5、在application文件中添加配置
# 真实数据源名称,多个数据源用逗号区分
spring.shardingsphere.datasource.names=m1
#配置数据源具体内容
spring.shardingsphere.datasource.m1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.m1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m1.jdbc-url=jdbc:mysql://localhost:3306/course_db?serverTimezone=GMT%2B8
spring.shardingsphere.datasource.m1.username=root
spring.shardingsphere.datasource.m1.password=1234
#绑定course表分布情况,配置表在哪个数据库里面,表名称都是什么 tables后的为规则course $->{1..2}为表达式,为表的拼接分布情况
spring.shardingsphere.sharding.tables.course.actual-data-nodes=m1.course_$->{0..9}
#分片所用到的字段
spring.shardingsphere.sharding.tables.course.table-strategy.standard.sharding-column=id
#精确分片策略
spring.shardingsphere.sharding.tables.course.table-strategy.standard.precise-algorithm-class-name=com.example.demo.shardingutil.PreciseShardingConfig
#范围分片策略
spring.shardingsphere.sharding.tables.course.table-strategy.standard.range-algorithm-class-name=com.example.demo.shardingutil.RangeAlgorithmConfig
# 打开sql日志输出
spring.shardingsphere.props.sql.show=true
6、自定义分片算法
/**
* 自定义分片策略 -> 精确分片
*/
public class PreciseShardingConfig implements PreciseShardingAlgorithm<Long> {
@Override
public String doSharding(Collection<String> shardingValue, PreciseShardingValue<Long> preciseShardingValue) {
String tableName = preciseShardingValue.getLogicTableName();
Long id = preciseShardingValue.getValue();
tableName = String.join("_", tableName, String.valueOf(id % 10L));
if (tableName.contains(tableName)) {
return tableName;
}
throw new IllegalArgumentException("分片失败");
}
}
/**
* 分片策略----> 范围分片 该分片可作为时间分片使用,此方法仅仅只是测试用方法,不可使用
*/
public class RangeAlgorithmConfig implements RangeShardingAlgorithm<Integer> {
@Override
public Collection<String> doSharding(Collection<String> shardingValue, RangeShardingValue<Integer> rangeShardingValue) {
Set<String> setList = Sets.newHashSet();
String logicTableName = rangeShardingValue.getLogicTableName();
for (int i = 0; i < 10; i++) {
String tableName = String.join("_",logicTableName,String.valueOf((int) (Math.random() * 10)));
setList.add(tableName);
}
return setList;
}
}