ShardingSphere初探?Shardingsphere支持oracle吗

ShardingSphere初探ShardingSphere初探 文章目录 ShardingSphere初探ShardingSphere主要组件核心功能优点Sharding-JDBC和Sharding-proxy的对比 Sharding-j

ShardingSphere初探

文章目录

初探ShardingSphere主要组件、核心特性及优势,以及Sharding-JDBC与Sharding-proxy对比

Sharding-jdbc水平分表demo:逻辑表和物理表的水平分片,选择分片键和分片算法Sharding-jdbc基于SpringBoot演示

Sharding-jdbc 水平分库分表演示查询演示范围自定义标准策略查询自定义复合策略自定义提示策略

ShardingSphere

ShardingSphere是一个分布式数据库中间件生态系统,旨在解决分布式数据库架构问题。它提供数据分片、读写隔离、弹性伸缩、分布式事务、数据加密等功能,帮助企业构建高性能、可扩展的分布式数据库解决方案。它是一个由Apache 软件基金会培育和维护的开源项目。

主要组件

分片-JDBC:

它是一个嵌入到应用程序中的轻量级Java 框架,提供JDBC 连接池和SQL 解析、重写和执行等功能。通过在应用层实现分片逻辑,支持各种关系型数据库。分片代理:

它是一个独立的代理层,支持兼容MySQL和PostgreSQL协议的客户端。它拦截SQL请求,执行分片、读写分离等操作,并将聚合结果返回给客户端。 Sharding-Sidecar(在Kubernetes 中也称为Sharding-Sphere):

它是专为Kubernetes 环境设计的微服务解决方案,采用Sidecar 模式实现数据库分片和读写隔离,适合云原生应用。

核心功能

数据分片:

水平表和数据库分区在多个数据库实例之间分布和存储数据,从而提高系统可扩展性和性能。 读写分离:

主从复制将读写请求分离,减少主库的负载,提高读操作的性能。 分布式交易:

支持XA、BASE等分布式事务协议,保证分布式环境下数据的一致性。 弹性收缩:

在线添加或删除数据库节点并动态调整分片规则以弹性扩展您的系统。 数据加密:

配备数据加密功能,确保存储数据的安全。

优点

开源和社区支持:ShardingSphere是Apache基金会的顶级项目,拥有活跃的社区和丰富的文档资源。灵活性:支持多种数据库,兼容性强,易于与现有系统集成。高性能:分片、读写分离,提高数据库并发性。易于扩展:弹性缩减功能使系统能够响应动态变化的业务需求。

ShardingSphere适用于需要高可用性、高性能、高扩展性的分布式数据库应用场景,例如互联网、电商、金融等行业。

Sharding-JDBC和Sharding-proxy的对比

特性Sharding-JDBCSharding-Proxy 架构类型嵌入式代理层部署位置应用内独立部署服务器之间适用语言Java 支持兼容MySQL、PostgreSQL 协议的客户端高性能(无网络开销) 网络延迟和代理层性能透明透明发送到客户端只需配置代理地址支持的数据库,如MySQL、PostgreSQL、Oracle、SQL Server等。支持数据分片。支持兼容性与ORM框架(Hibernate、MyBatis等)无缝集成兼容所有遵循协议的客户端部署、运维需要集中管理各个应用中的部署和配置,简化客户端部署。您可以通过添加应用程序代理节点轻松扩展程序的可扩展性。为了增加应用程序内的复杂性,必须更改和配置应用程序的中央配置以降低应用程序的复杂性。中型系统、单体应用、大型系统、微服务架构需要支持多语言环境

Sharding-JDBC适用于需要高性能和对数据库操作进行细粒度控制的中小型Java应用程序。

Sharding-Proxy 适用于需要独立于语言的解决方案的大型系统或微服务架构。

Sharding-jdbc水平分表演示

水平分表

概念:将一个大表中的数据按照一定的规则(例如根据用户ID)划分为多个小表,每个小表包含一部分数据。好处:减少单表大小,提高查询和写入性能。缺点:你必须处理查询以及表之间数据的平衡分配。

当然如果你有逻辑表的话,详细的SQL如下:

创建表“课程”(

`cid` bigint NOT NULL AUTO_INCRMENT,

`cname` varchar(255) 字符集utf8mb4 整理utf8mb4_general_ci 默认为NULL,

`user_id` bigint 默认为NULL,

`cstatus` varchar(255) 字符集utf8mb4 COLLATE utf8mb4_general_ci 默认NULL,

主键(`cid`)

) 引擎=InnoDB AUTO_INCRMENT=1012831258863996929 默认字符集=utf8mb4 COLLATE=utf8mb4_general_ci;RSET=utf8mb4 COLLATE=utf8mb4_general_ci;

逻辑表和物理表划分

这时由于业务原因需要对课程表进行横向划分。具体划分规则如下。分为course_1 和course_2。在这种情况下,course_1和course_2是实际存储数据的物理表。

对应的表SQL为:但表名不同,字段完全相同。创建这两个表。

创建表`course_1` (

`cid` bigint NOT NULL AUTO_INCRMENT,

`cname` varchar(255) 字符集utf8mb4 整理utf8mb4_general_ci 默认为NULL,

`user_id` bigint 默认为NULL,

`cstatus` varchar(255) 字符集utf8mb4 COLLATE utf8mb4_general_ci 默认NULL,

主键(`cid`)

) 引擎=InnoDB AUTO_INCRMENT=1012831258863996929 默认字符集=utf8mb4 COLLATE=utf8mb4_general_ci;RSET=utf8mb4 COLLATE=utf8mb4_general_ci;

创建表`course_2` (

`cid` bigint NOT NULL AUTO_INCRMENT,

`cname` varchar(255) 字符集utf8mb4 整理utf8mb4_general_ci 默认为NULL,

`user_id` bigint 默认为NULL,

`cstatus` varchar(255) 字符集utf8mb4 COLLATE utf8mb4_general_ci 默认NULL,

主键(`cid`)

) 引擎=InnoDB AUTO_INCRMENT=1012831258863996929 默认字符集=utf8mb4 COLLATE=utf8mb4_general_ci;RSET=utf8mb4 COLLATE=utf8mb4_general_ci;

分片键和分片算法的选取

cid的唯一性使得我们可以使用雪花算法生成cid,并使用哈希算法对cid进行加密并将其均匀分布在每个数据分片中。

对应的分片算法为shard=(cid % 2 + 1)。

Sharding-jdbc 基于SpringBoot演示

为sharding-demo-1创建一个SpringBoot项目,并引入以下依赖:

依赖关系

依赖

groupIdorg.springframework.boot/groupId

artifactId spring boot 启动器/artifactId

/依赖

依赖

groupIdorg.springframework.boot/groupId

artifactIdspring-boot-starter-test/artifactId

/依赖

依赖

组IDmysql/组ID

artifactIdmysql-connector-java/artifactId

/依赖

依赖

groupIdcom.alibaba/群组ID

artifactIddruid/artifactId

版本1.1.23/版本

/依赖

依赖

groupIdcom.baomidou/groupId

artifactIdmybatis-plus-boot-starter/artifactId

版本3.3.2/版本

/依赖

依赖

groupIdorg.apache.shardingsphere/groupId

artifactIdsharding-jdbc-spring-boot-starter/artifactId

版本4.1.1/版本

/依赖

依赖

groupIdjunit/组ID

工件Idjunit/artifactId

范围测试/范围

/依赖

/依赖项

实体表创建课程

公开课课程{

私有长cid;

私有字符串cname;

@TableField(\’user_id\’)

私人长用户ID。

私有字符串cstatus;

.getter setter toString

}

创建课程映射器

@映射器

公共接口CourseMapper 扩展BaseMapperCourse {

}

配置sharding-jdbc相关参数

弹簧:

分片球体:

数据来源:

#设置第一个数据源m1

名称: m1

#设置第一个数据源m1的详细信息

m1:

type: com.alibaba.druid.pool.DruidDataSource

驱动程序类名: com.mysql.cj.jdbc.Driver

url: jdbc:mysql://192.168.56.102:3306/coursedb?serverTimezone=UTCuseSSL=falseallowPublicKeyRetrieval=true

用户名: root

密码: 123456

#设置分片表详细信息

分片:

表:

#配置逻辑表过程主键生成规则和详细分片策略

课程:

#设置逻辑表和物理表的关系。然后课程分为course_1 和course_2。

实际数据节点: m1.course_$-{1.2}

# 设置主键生成规则

密钥生成器:

栏目:cid

:型雪花

道具:

工人:

id: 1

表策略:

内联:

# 设置分片键

分片列:cid

#设置分片算法

算法表达式: course_$-{cid % 2 + 1}

道具:

SQL:

#sp 打开SQL日志

显示: 正确

创建ShardingTest 测试

@SpringBootTest

@RunWith(SpringRunner.class)

公共类ShardingTest {

@资源

私人课程映射器课程映射器;

@测试

公共无效添加课程(){

for (int i=0; i 10; i++) {

课程course=new Course();

course.setCname(\’c++\’);

course.setUserid(180L);

course.setCstatus(\’2\’);

courseMapper.插入(课程);

}

}

@测试

公共无效findCourse(){

QueryWrapperCourse objectQueryWrapper=new QueryWrapper();

ListCourse course=courseMapper.selectList(objectQueryWrapper);

System.out.println(courses.size());

}

}

运行addCourse()并监控数据是否插入到数据库中。

course_1的内容如下:

cidcnameuser_idcstatus1012880134358700032c++18021012880134933319680c++18021012880135017205760c++18021012880135096897536c++1802101288013515 9812096c++1802

course_2的内容如下:

cidcnameuser_idcstatus1012880134887182337c++18021012880134979457025c++18021012880135046565889c++18021012880135130451969c++1802101288013518 0783617c++1802

查看控制台日志

2024-06-27 00:24:02.517信息24260 — [主要] ShardingsPhere-SQL : SQLSTATEMENT: INSERTSTATEMENTCONTEXT(SUPER=COOMSONSQLSTATEMENTCONTEMTCONTEMT) Enement@ e91af 20,TablesContext=org.apache.shardingsphere.sql.parser.binder.segment.table.TablesContext@6221b13b),tablesContext=org.apache.shardingsphere.sql.parser.binder.segment.table.TablesContext@6221b13b,columnNames=[cname, user_id, cstatus ]、insertValueContexts=[InsertValueContext(parametersCount=3、valueExpressions=[ParameterMarkerExpressionSegment(startIndex=59、stopIndex=59、parameterMarkerIndex=0)、ParameterMarkerExpressionSegment(startIndex=62、stopIndex=62、parameterMarkerIndex=1)、ParameterMarkerExpressionSegment(startIndex=65) , stopIndex=65,parameterMarkerIndex=2),DerivedParameterMarkerExpressionSegment(super=ParameterMarkerExpressionSegment(startIndex=0, stopIndex=0,parameterMarkerIndex=3))],parameters=[c++, 180, 2])], generatedKeyContext=Optional[GenerateKeyContext(columnName)=)cid,生成=true,生成值=[1012880134358700032])])

2024-06-27 00:24:02.518 INFO 24260 — [main] ShardingSphere-SQL : 实际SQL: m1 : INSERT INTO course_1 (cname,

用户身份,

cstatus, cid) 值(?) : [c++, 180, 2, 1012880134358700032]

2024-06-27 00:24:02.560 INFO 24260 — [main] ShardingSphere-SQL : 逻辑SQL: INSERT INTO 课程(cname,

用户身份,

cstatus ) 值(?

?

? )

包含雪花算法生成的ID值

实际SQL表示实际执行的SQL语句。

m1 : 插入course_1 (cname,

用户身份,

cstatus, cid) 值(?) : [c++, 180, 2, 1012880134358700032]

逻辑SQL:表示逻辑SQL语句

插入课程(cname,

用户身份,

cstatus ) 值(?

?

? )

ShardingSphere通过分片策略传递分片键,将逻辑SQL转换为实际执行的SQL。

Sharding-jdbc水平分库分表演示

您需要在yaml 中配置第二个库,并在第二个库中创建新的course_1 和course_2 表。

弹簧:

分片球体:

数据来源:

#设置两个数据源m1和m2

名称: m1, m2

#设置第一个数据源m1的详细信息

m1:

type: com.alibaba.druid.pool.DruidDataSource

驱动程序类名: com.mysql.cj.jdbc.Driver

url: jdbc:mysql://47.109.94.124:3306/coursedb?serverTimezone=UTCuseSSL=falseallowPublicKeyRetrieval=true

用户名: root

密码: 123456

#设置第二个数据源m2的详细信息

m2:

type: com.alibaba.druid.pool.DruidDataSource

驱动程序类名: com.mysql.cj.jdbc。

Driver
url: jdbc:mysql://47.109.188.99:3306/coursedb?serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: 123456
#配置分片表的详细信息
sharding:
tables:
#配置逻辑表course的主键生成规则和详细的分片策略
course:
#配置逻辑表和物理表之间的关系,此时将m分成m1和m2将course分成course_1和course_2
actual-data-nodes: m$->{1..2}.course_$->{1..2}
# 配置主键生成规则
key-generator:
column: cid
type: SNOWFLAKE
props:
worker:
id: 1
#配置库的策略
database-strategy:
inline:
# 配置分片键
sharding-column: cid
#配置库的分片算法
algorithm-expression: m$->{cid % 2 + 1}
table-strategy:
inline:
# 配置分片键
sharding-column: cid
#配置分片算法
algorithm-expression: course_$->{((cid+1)%4).intdiv(2)}
props:
sql:
#开启sp sql日志
show: true

查询演示

查询所有的course表信息

public void findCourse(){
QueryWrapper<Course> objectQueryWrapper = new QueryWrapper<>();
List<Course> courses = courseMapper.selectList(objectQueryWrapper);
System.out.println(courses.size());
}

2024-06-27 16:48:18.195 INFO 20524 — [ main] ShardingSphere-SQL : Logic SQL: SELECT cid,cname,user_id,cstatus FROM course
2024-06-27 16:48:18.195 INFO 20524 — [ main] ShardingSphere-SQL : SQLStatement: SelectStatementContext(super=CommonSQLStatementContext(sqlStatement=org.apache.shardingsphere.sql.parser.sql.statement.dml.SelectStatement@1d3c112a, tablesContext=org.apache.shardingsphere.sql.parser.binder.segment.table.TablesContext@2a140ce5), tablesContext=org.apache.shardingsphere.sql.parser.binder.segment.table.TablesContext@2a140ce5, projectionsContext=ProjectionsContext(startIndex=8, stopIndex=32, distinctRow=false, projections=[ColumnProjection(owner=null, name=cid, alias=Optional.empty), ColumnProjection(owner=null, name=cname, alias=Optional.empty), ColumnProjection(owner=null, name=user_id, alias=Optional.empty), ColumnProjection(owner=null, name=cstatus, alias=Optional.empty)]), groupByContext=org.apache.shardingsphere.sql.parser.binder.segment.select.groupby.GroupByContext@1f71194d, orderByContext=org.apache.shardingsphere.sql.parser.binder.segment.select.orderby.OrderByContext@db99785, paginationContext=org.apache.shardingsphere.sql.parser.binder.segment.select.pagination.PaginationContext@70716259, containsSubquery=false)
2024-06-27 16:48:18.195 INFO 20524 — [ main] ShardingSphere-SQL : Actual SQL: m1 ::: SELECT cid,cname,user_id,cstatus FROM course_1
2024-06-27 16:48:18.196 INFO 20524 — [ main] ShardingSphere-SQL : Actual SQL: m1 ::: SELECT cid,cname,user_id,cstatus FROM course_2
2024-06-27 16:48:18.196 INFO 20524 — [ main] ShardingSphere-SQL : Actual SQL: m2 ::: SELECT cid,cname,user_id,cstatus FROM course_1
2024-06-27 16:48:18.196 INFO 20524 — [ main] ShardingSphere-SQL : Actual SQL: m2 ::: SELECT cid,cname,user_id,cstatus FROM course_2

根据实际执行sql看出,其实是将m1,m2的course_1和course_2都去执行一遍SELECT cid,cname,user_id,cstatus FROM course_$,最后再聚合,将数据返回。

范围查询

根据cid的范围查询数据,如1L 到 1806251962652463105L

public void findRangeCourse(){
QueryWrapper<Course> objectQueryWrapper = new QueryWrapper<>();
objectQueryWrapper.between(\”cid\”, 1L, 1806251962652463105L);
List<Course> courses = courseMapper.selectList(objectQueryWrapper);
System.out.println(courses.size());
}

此时由于是inline的关系,会抛异常

Cause: java.lang.IllegalStateException: Inline strategy cannot support this type sharding:RangeRouteValue(columnName=cid, tableName=course, valueRange=[1‥1806251962652463105])

分片策略是inline无法支持范围查询。

标准策略的定制

Sharding-jdbc支持分库分表的标准策略模式,可以根据自己需求定制策略。

分为精准策略和range策略.

精准策略需要实现PreciseShardingAlgorithm,range策略需要实现RangeShardingAlgorithm
下面分别定义库和表的策略,其中库的策略为

public class CourseDataSourcePrecisAlgorithm implements PreciseShardingAlgorithm<Long> {
private static final AtomicInteger COUNTER = new AtomicInteger(0);
/**
* 从availableTargetNames中根据分片键preciseShardingValue的值,选择一个数据节点名称。
*
* @param availableTargetNames 参数包含了所有可用的数据节点名称,比如数据源或数据表的名称。
* @param preciseShardingValue 参数包含了分片键的值和逻辑表名称。
* @return
*/
@Override
public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> preciseShardingValue) {
// 获取分片键的值
//选取数据源m1,m2
int andIncrement = COUNTER.getAndIncrement();
if(andIncrement % 2 == 0){
return \”m1\”;
}else{
return \”m2\”;
}
}
}

range并没有策略,此时返回所有的库,则ShardingSphere在执行范围查询的时候,会遍历所有的库。

public class CourseDataSourceRangeAlgorithm implements RangeShardingAlgorithm<Long> {
@Override
public Collection<String> doSharding(Collection<String> availableTargetNames, RangeShardingValue<Long> rangeShardingValue){
return availableTargetNames;
}
}

表的策略为

public class CourseDataSourcePrecisAlgorithm implements PreciseShardingAlgorithm<Long> {
/**
* 从availableTargetNames中根据分片键preciseShardingValue的值,选择一个数据节点名称。
* 选取数据源m1,m2
* 因为有4张表,所以利用cid对4取模,得到一个余数,余数是如果是0和1,则选择m1,如果是2和3,则选择m2
* @param availableTargetNames 参数包含了所有可用的数据节点名称,比如数据源或数据表的名称。
* @param preciseShardingValue 参数包含了分片键的值和逻辑表名称。
* @return
*/
@Override
public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> preciseShardingValue) {
// 获取分片键的值
Long cid = preciseShardingValue.getValue();
long mod = cid % 4;
if(mod == 0 || mod == 1){
return \”m1\”;
}else if(mod == 2 || mod == 3){
return \”m2\”;
}else{
throw new UnsupportedOperationException();
}
}
}

public class CourseTablePrecisAlgorithm implements PreciseShardingAlgorithm<Long> {
/**
* 因为有4张表,所以利用cid对4取模,得到一个余数,
* 余数如果是0和1,则选择m1,如果是0,则选择m1->course_1,如果是1,则选择m1->course_2
* 余数如果是2和3,则选择m2,,如果是2,则选择m2->course_1,如果是3,则选择m2->course_2
* 这里由于雪花算法在低并发下,由于同一毫秒只分配一个id则最后12位都是0,所以不存在2^0,故而雪花生成的id是2,4的倍数,取模偏移0区
* 数据量少时或者tps低时尽量避免取模2,4,如分片键
* @param collection
* @param preciseShardingValue
* @return
*/
@Override
public String doSharding(Collection<String> collection, PreciseShardingValue<Long> preciseShardingValue) {
//怎么根据cid来判断路由到哪个表,cid这里既需要经过算法成为1,也要成为2,还不能跟dataSource路由冲突
long mod = preciseShardingValue.getValue() % 4;
//根据mod能知道该条数据应该路由到哪个库中
if(mod == 0 || mod == 2){
String key = preciseShardingValue.getLogicTableName() + \”_\” + 1;
if(collection.contains(key)){
return key;
}
throw new UnsupportedOperationException();
}else if(mod == 1 || mod == 3){
String key = preciseShardingValue.getLogicTableName() + \”_\” + 2;
if(collection.contains(key)) {
return key;
}
throw new UnsupportedOperationException();
}
throw new UnsupportedOperationException();
}
}

yaml中需要更改为如下配置

spring:
shardingsphere:
datasource:
#配置第一个数据源m1
names: m1,m2
#配置第一个数据源m1的详细信息
m1:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://47.109.94.124:3306/coursedb?serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: SXD6VRjq
m2:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://47.109.188.99:3306/coursedb?serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: xDLnuQtK
#配置分片表的详细信息
sharding:
tables:
#配置逻辑表course的主键生成规则和详细的分片策略
course:
#配置逻辑表和物理表之间的关系,此时将course分成course_1和course_2
actual-data-nodes: m$->{1..2}.course_$->{1..2}
# 配置主键生成规则
key-generator:
column: cid
type: SNOWFLAKE
props:
worker:
id: 1
#配置库的策略
database-strategy:
standard:
# 配置分片策略
precise-algorithm-class-name: cn.axj.sharding.ShardingAlgorithmConfig.CourseDataSourcePrecisAlgorithm
range-algorithm-class-name: cn.axj.sharding.ShardingAlgorithmConfig.CourseDataSourceRangeAlgorithm
# 配置分片键
sharding-column: cid
table-strategy:
standard:
range-algorithm-class-name: cn.axj.sharding.ShardingAlgorithmConfig.CourseTableRangeAlgorithm
precise-algorithm-class-name: cn.axj.sharding.ShardingAlgorithmConfig.CourseTablePrecisAlgorithm
# 配置分片键
sharding-column: cid
props:
sql:
#开启sp sql日志
show: true

执行范围查询

public void findRangeCourse(){
QueryWrapper<Course> objectQueryWrapper = new QueryWrapper<>();
objectQueryWrapper.between(\”cid\”, 1L, 1806251962652463105L);
List<Course> courses = courseMapper.selectList(objectQueryWrapper);
System.out.println(courses.size());
}

2024-06-27 17:27:00.263 INFO 11432 — [ main] ShardingSphere-SQL : Actual SQL: m1 ::: SELECT cid,cname,user_id,cstatus FROM course_1

WHERE (cid BETWEEN ? AND ?) ::: [1, 1806251962652463105]
2024-06-27 17:27:00.263 INFO 11432 — [ main] ShardingSphere-SQL : Actual SQL: m1 ::: SELECT cid,cname,user_id,cstatus FROM course_2

WHERE (cid BETWEEN ? AND ?) ::: [1, 1806251962652463105]
2024-06-27 17:27:00.263 INFO 11432 — [ main] ShardingSphere-SQL : Actual SQL: m2 ::: SELECT cid,cname,user_id,cstatus FROM course_1

WHERE (cid BETWEEN ? AND ?) ::: [1, 1806251962652463105]
2024-06-27 17:27:00.263 INFO 11432 — [ main] ShardingSphere-SQL : Actual SQL: m2 ::: SELECT cid,cname,user_id,cstatus FROM course_2

可以看到实际执行sql如上。每个库每个表都查询,最后聚合。

标准策略针对in、=、between三种范围查询

复合策略的定制

多个字段组合的查询,则需要用到复合策略complex

spring:
shardingsphere:
datasource:
#配置第一个数据源m1
names: m1,m2
#配置第一个数据源m1的详细信息
m1:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://47.109.94.124:3306/coursedb?serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: SXD6VRjq
m2:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://47.109.188.99:3306/coursedb?serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: xDLnuQtK
#配置分片表的详细信息
sharding:
tables:
#配置逻辑表course的主键生成规则和详细的分片策略
course:
#配置逻辑表和物理表之间的关系,此时将course分成course_1和course_2
actual-data-nodes: m$->{1..2}.course_$->{1..2}
# 配置主键生成规则
key-generator:
column: cid
type: SNOWFLAKE
props:
worker:
id: 1
#配置库的策略
database-strategy:
complex:
#配置分片键
sharding-columns: cid,user_id
# 配置分片策略
algorithm-class-name: cn.axj.sharding.ShardingAlgorithmConfig.CourseDatabaseComplexAlgorithm
table-strategy:
complex:
sharding-columns: cid,user_id
algorithm-class-name: cn.axj.sharding.ShardingAlgorithmConfig.CourseTableComplexAlgorithm
props:
sql:
#开启sp sql日志
show: true

public class CourseDatabaseComplexAlgorithm implements ComplexKeysShardingAlgorithm<Long> {

@Override
public Collection<String> doSharding(Collection<String> availableTargetNames, ComplexKeysShardingValue<Long> complexKeysShardingValue) {
Long userId = complexKeysShardingValue.getColumnNameAndShardingValuesMap().get(\”cid\”).iterator().next();
Long cid = complexKeysShardingValue.getColumnNameAndShardingValuesMap().get(\”cid\”).iterator().next();
// 自定义分片逻辑,示例中简单处理
// 假设根据 user_id 和 order_id 进行取模分片
String dataSourceName = \”m\” + ((userId + cid) % availableTargetNames.size() + 1);
for (String targetName : availableTargetNames) {
if (targetName.endsWith(dataSourceName)) {
return Collections.singleton(targetName); // 返回匹配的表名
}
}
throw new IllegalArgumentException(\”No precise sharding available for \” + complexKeysShardingValue);
}
}

public class CourseTableComplexAlgorithm implements ComplexKeysShardingAlgorithm<Long> {
@Override
public Collection<String> doSharding(Collection<String> availableTargetNames, ComplexKeysShardingValue<Long> complexKeysShardingValue) {
Long userId = complexKeysShardingValue.getColumnNameAndShardingValuesMap().get(\”cid\”).iterator().next();
Long cid = complexKeysShardingValue.getColumnNameAndShardingValuesMap().get(\”cid\”).iterator().next();
// 自定义分片逻辑,示例中简单处理
// 假设根据 user_id 和 order_id 进行取模分片
String tableName = complexKeysShardingValue.getLogicTableName() + \”_\” + ((userId + cid) % availableTargetNames.size() + 1);
for (String targetName : availableTargetNames) {
if (targetName.endsWith(tableName)) {
return Collections.singleton(targetName); // 返回匹配的表名
}
}
throw new IllegalArgumentException(\”No precise sharding available for \” + complexKeysShardingValue);
}
}

hint策略的定制

hint策略,按照与sql无关的值进行分片,所以无需分片键这些,只需要一个分片算法

分片的值通过HintManger手动设置, 如下示例。

AtomicInteger atomicInteger = new AtomicInteger(0);
HintManager instance = HintManager.getInstance();
instance.setDatabaseShardingValue(atomicInteger.getAndIncrement() % 2 + 1);
instance.addTableShardingValue(\”course\”, atomicInteger.getAndIncrement() % 2 + 1);

public class CourseDatabaseHintAlgorithm implements HintShardingAlgorithm<String> {
@Override
public Collection<String> doSharding(Collection<String> collection, HintShardingValue<String> hintShardingValue) {
String key = \”m\” + hintShardingValue.getValues().toArray()[0];
if(collection.contains(key)){
return Collections.singletonList(key);
}
throw new UnsupportedOperationException();
}
}

public class CourseTableHintAlgorithm implements HintShardingAlgorithm<Long> {
@Override
public Collection<String> doSharding(Collection<String> availableTargetNames, HintShardingValue<Long> shardingValue){
String logicTableName = shardingValue.getLogicTableName();
//该值需要在查询或者DDL的时候通过HintManager设置
Collection<Long> values = shardingValue.getValues();
String key = logicTableName + \”_\” + shardingValue.getValues().toArray()[0];
if(availableTargetNames.contains(key)){
return Collections.singletonList(key);
}
throw new UnsupportedOperationException();
}
}

spring:
shardingsphere:
datasource:
#配置第一个数据源m1
names: m1,m2
#配置第一个数据源m1的详细信息
m1:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://47.109.94.124:3306/coursedb?serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: SXD6VRjq
m2:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://47.109.188.99:3306/coursedb?serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: xDLnuQtK
#配置分片表的详细信息
sharding:
tables:
#配置逻辑表course的主键生成规则和详细的分片策略
course:
#配置逻辑表和物理表之间的关系,此时将course分成course_1和course_2
actual-data-nodes: m$->{1..2}.course_$->{1..2}
# 配置主键生成规则
key-generator:
column: cid
type: SNOWFLAKE
props:
worker:
id: 1
#配置库的策略
database-strategy:
hint:
algorithm-class-name: cn.axj.sharding.ShardingAlgorithmConfig.CourseDatabaseHintAlgorithm
table-strategy:
hint:
algorithm-class-name: cn.axj.sharding.ShardingAlgorithmConfig.CourseTableHintAlgorithm
props:
sql:
#开启sp sql日志
show: true

比如在新增数据的时候,需要利用HintManage将分片值传进去

public void addHintCourse(){
AtomicInteger atomicInteger = new AtomicInteger(0);
HintManager instance = HintManager.getInstance();
for (int i = 0; i < 200; i++) {
instance.setDatabaseShardingValue(atomicInteger.getAndIncrement() % 2 + 1);
instance.addTableShardingValue(\”course\”, atomicInteger.getAndIncrement() % 2 + 1);
Course course = new Course();
course.setCname(\”c++\”);
course.setUserid(180L);
course.setCstatus(\”2\”);
courseMapper.insert(course);
}
}

#以上关于ShardingSphere初探的相关内容来源网络仅供参考,相关信息请以官方公告为准!

原创文章,作者:CSDN,如若转载,请注明出处:https://www.sudun.com/ask/92654.html

Like (0)
CSDN的头像CSDN
Previous 2024年6月28日
Next 2024年6月28日

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注