Sharding-JDBC(数据分片)学习记录

Sharding-JDBC(数据分片)学习记录

一、sharding-jdbc是什么?

定位为轻量级 Java 框架,在 Java 的 JDBC 层提供的额外服务。
它使用客户端直连数据库,以 jar
包形式提供服务,无需额外部署和依赖,可理解为增强版的 JDBC 驱动,完全兼容 JDBC
和各种 ORM 框架。

  • 适用于任何基于 JDBC 的 ORM 框架,如:JPA, Hibernate, Mybatis, Spring JDBC
    Template 或直接使用 JDBC。

  • 支持任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP 等。

  • 支持任意实现 JDBC 规范的数据库,目前支持
    MySQL,Oracle,SQLServer,PostgreSQL 以及任何遵循 SQL92 标准的数据库。

在这里插入图片描述

二、sharding-jdbc的核心概念

  • 逻辑表(LogicTable):进行水平拆分的时候同一类型(逻辑、数据结构相同)的表的总称。例:订单数据根据主键尾数拆分为10张表,分别是t_order_0到t_order_9,他们的逻辑表名为t_order。

  • 真实表(ActualTable):在分片的数据库中真实存在的物理表。即上个示例中的t_order_0到t_order_9。

  • 数据节点(DataNode):数据分片的最小单元。由数据源名称和数据表组成,例:ds_0.t_order_0。

  • 动态表(DynamicTable):逻辑表和物理表不一定需要在配置规则中静态配置。如,按照日期分片的场景,物理表的名称随着时间的推移会产生变化。

  • 绑定表(BindingTable):指分片规则一致的主表和子表。例如:t_order表和t_order_item表,均按照order_id分片,则此两张表互为绑定表关系。绑定表之间的多表关联查询不会出现笛卡尔积关联,关联查询效率将大大提升。

  • 分片键(ShardingColumn):分片字段用于将数据库(表)水平拆分的字段,支持单字段及多字段分片。例如上例中的order_id。

  • 分片算法(ShardingAlgorithm):进行水平拆分时采用的算法,分片算法需要应用方开发者自行实现,可实现的灵活度非常高。

  • 分片策略(ShardingStrategy):包含分片键和分片算法,由于分片算法的独立性,将其独立抽离。

三、如何使用sharing-jdbc配置

1、引入maven依赖

<dependency>

<groupId>org.apache.shardingsphere</groupId>

<artifactId>shardingsphere-jdbc-core</artifactId>

<version>${latest.release.version}</version>

</dependency>

注意: 请将${latest.release.version}更改为实际的版本号。

2、规则配置

Sharding-JDBC可以通过Java,YAML,Spring命名空间和Spring Boot
Starter四种方式配置,开发者可根据场景选择适合的配置方式。(此处我通过Spring
Boot进行配置)

3、创建数据源

# 配置真实数据源  
spring.shardingsphere.datasource.names=ds0,ds1  
(此处的数据源名称可以配置多个,ds0、ds1相当于给数据源起别名)  
# 配置第 1 个数据源  
spring.shardingsphere.datasource.ds0.type=com.zaxxer.hikari.HikariDataSource  
spring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.jdbc.Driver  
spring.shardingsphere.datasource.ds0.jdbc-url=jdbc:mysql://localhost:3306/test_sharding_jdbc_01\?useUnicode=true&characterEncoding=UTF-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true
spring.shardingsphere.datasource.ds0.username=root  
spring.shardingsphere.datasource.ds0.password=*****  
# 配置第 2 个数据源  
spring.shardingsphere.datasource.ds1.type=com.zaxxer.hikari.HikariDataSource  
spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.jdbc.Driver  
spring.shardingsphere.datasource.ds1.jdbc-url=jdbc:mysql://localhost:3306/test_sharding_jdbc_02\?useUnicode=true&characterEncoding=UTF-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true
spring.shardingsphere.datasource.ds1.username=root  
spring.shardingsphere.datasource.ds1.password=*****  
#配置默认数据库

spring.shardingsphere.sharding.default-data-source-name=ds0

四、分库案例

新建数据库test_sharding_jdbc_01、test_sharding_jdbc_02

两个库中建表tb_user0(结构一致)

在这里插入图片描述

1、精准分片(分库)

配置:

#由数据源名 + 表名组成,以小数点分隔。多个表以逗号分隔,支持inline表达式。

spring.shardingsphere.sharding.tables.tb_user.actual-data-nodes=ds$->{0..1}.tb_user0

#分片列名称

spring.shardingsphere.sharding.tables.tb_user.database-strategy.standard.sharding-column=age

#精确分片算法类名称(需实现PreciseShardingAlgorithm类,提供具体的分片规则)

spring.shardingsphere.sharding.tables.tb_user.database-strategy.standard.precise-algorithm-class-name=org.quzb.sharding_jdbc.config.MyPreciseShardingAlgorithm

#自增列生成器类型,缺省表示不使用自增主键生成器(内置类型:SNOWFLAKE、UUID)

spring.shardingsphere.sharding.tables.tb_user.key-generator.type=SNOWFLAKE

spring.shardingsphere.sharding.tables.tb_user.key-generator.column=id

精准分片实现类:

public class MyPreciseShardingAlgorithm implements
PreciseShardingAlgorithm<Integer> {  
@Override  
public String doSharding(Collection<String> collection,
PreciseShardingValue<Integer> preciseShardingValue) {  
//接收到的分片列"age"的值  
Integer value = preciseShardingValue.getValue();  
//collection:配置的数据库集合,分片规则(自行定义):将接收到的age%2返回对应的数据库名

return (String) collection.toArray()[value % collection.size()];  
}  
}  

在这里插入图片描述

测试使用:

在这里插入图片描述

针对指定字段将数据插入不同的库中,说明分库分片成功

2、范围分片(分库)

配置:

spring.shardingsphere.sharding.tables.tb_user.key-generator.type=SNOWFLAKE

spring.shardingsphere.sharding.tables.tb_user.key-generator.column=id

# 范围分片

spring.shardingsphere.sharding.tables.tb_user.actual-data-nodes=ds$->{0..1}.tb_user0

spring.shardingsphere.sharding.tables.tb_user.database-strategy.standard.sharding-column=age

spring.shardingsphere.sharding.tables.tb_user.database-strategy.standard.range-algorithm-class-name=org.quzb.sharding_jdbc.config.MyRangeShardingAlgorithm

spring.shardingsphere.sharding.tables.tb_user.database-strategy.standard.precise-algorithm-class-name=org.quzb.sharding_jdbc.config.MyRangeShardingAlgorithm

范围分片实现类:

public class MyRangeShardingAlgorithm implements
PreciseShardingAlgorithm<Integer>, RangeShardingAlgorithm<Integer> {

@Override

public Collection<String> doSharding(Collection<String> collection,
RangeShardingValue<Integer> rangeShardingValue) {

Set<String> result= Sets.newHashSet();

Integer lowerEndpoint = rangeShardingValue.getValueRange().lowerEndpoint();

Integer upperEndpoint = rangeShardingValue.getValueRange().upperEndpoint();

for(int i=lowerEndpoint;i<upperEndpoint;i++){

result.add((String) collection.toArray()[i%2]);

}

return result;

}

@Override

public String doSharding(Collection<String> collection,
PreciseShardingValue<Integer> preciseShardingValue) {

Integer value = preciseShardingValue.getValue();

if (value>10){  
return (String) collection.toArray()[0];  
	}  
return (String) collection.toArray()[1];  
}  
}  

测试结果:
在这里插入图片描述

3、复合算法分片(分库)

配置:

spring.shardingsphere.sharding.tables.tb_user.key-generator.type=SNOWFLAKE

spring.shardingsphere.sharding.tables.tb_user.key-generator.column=id

spring.shardingsphere.sharding.tables.tb_user.actual-data-nodes=ds$->{0..1}.tb_user0

#对user_year、age进行分片

spring.shardingsphere.sharding.tables.tb_user.database-strategy.complex.sharding-columns=user_year,age

spring.shardingsphere.sharding.tables.tb_user.database-strategy.complex.algorithm-class-name=org.quzb.sharding_jdbc.config.MartinComplexKeysShardingAlgorithm

实现类:

public class MartinComplexKeysShardingAlgorithm implements
ComplexKeysShardingAlgorithm<Integer> {

@Override

public Collection<String> doSharding(Collection<String> collection,
ComplexKeysShardingValue<Integer> complexKeysShardingValue) {

Map<String, Collection<Integer> columnNameAndShardingValuesMap =
complexKeysShardingValue.getColumnNameAndShardingValuesMap();

if
(columnNameAndShardingValuesMap.containsKey("age")&&columnNameAndShardingValuesMap.containsKey("user_year")){

Collection<Integer> ageList = columnNameAndShardingValuesMap.get("age");

Collection<Integer> yearList =columnNameAndShardingValuesMap.get("user_year");

Integer year = yearList.iterator().next();

Integer age = ageList.iterator().next();

int i =Objects.equals(age % collection.size(),0)?0:1;

if (Objects.equals(0,i)&&year>1998){

return Lists.newArrayList((String) collection.toArray()[0]);

}

return Lists.newArrayList((String) collection.toArray()[1]);

}
return collection;
}
}

测试结果:
在这里插入图片描述

五、分表示例
分表与分库类似

精准分片(分表)

配置:

#配置表名

spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=ds0.t_order_$->{['us','uk']}

#配置分片字段  
spring.shardingsphere.sharding.tables.t_order.table-strategy.standard.sharding-column=station

spring.shardingsphere.sharding.tables.t_order.table-strategy.standard.precise-algorithm-class-name=org.quzb.sharding_jdbc.config.OrderPreciseShardingAlgorithm

spring.shardingsphere.sharding.tables.t_order.key-generator.column=id  
spring.shardingsphere.sharding.tables.t_order.key-generator.type=SNOWFLAKE

实现类:

public class OrderPreciseShardingAlgorithm implements
PreciseShardingAlgorithm<String> {  
@Override  
public String doSharding(Collection<String> collection,
PreciseShardingValue<String> preciseShardingValue) {  
#value值为接收到的站点值  
String value = preciseShardingValue.getValue();  
String lowerCase = String.join("","t_order_",value.toLowerCase());  
#collection为配置的表名集合  
for (String coll:collection) {  
if (Objects.equals(lowerCase, coll)) {  
return coll;  
}  
}  
return null;  
}  
}  

测试结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VRNWO501-1611389911606)(media/2faf7a33ab8423318c73e3dfebe0a5b9.png)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lukNPZVw-1611389911607)(media/c3daeb124851e08cfa98ac026649d148.png)]
rCase = String.join("",“t_order_”,value.toLowerCase());
#collection为配置的表名集合
for (String coll:collection) {
if (Objects.equals(lowerCase, coll)) {
return coll;
}
}
return null;
}
}
测试结果:
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值