复合分片策略
原创大约 2 分钟
这种分片算法支持=
、IN
和BETWEEN AND
的分片操作,并且支持多分片键
。
这种算法不同的分片键
之间可能会有比较复杂的关系,所以ShardingSphere未做过多封装,全由开发者自己实现。
先创建一个自定义的CustomComplexShardingAlgorithm
类,让它实现ComplexKeysShardingAlgorithm<Long>
接口。
package com.itechthink.strategy;
import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingValue;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 自定义分库分表策略:复合分片算法
*
*/
public class CustomComplexShardingAlgorithm implements ComplexKeysShardingAlgorithm<Long> {
/**
* @param dataSourceNames 数据源集合
* 在分库时值为所有分片库的集合 databaseNames
* 分表时为对应分片库中所有分片表的集合 tablesNames
* @param complexKeysShardingValue 分片属性
* logicTableName 逻辑表名
* columnName 分片健
* value 从SQL中解析出的分片健值
*/
@Override
public Collection<String> doSharding(Collection<String> dataSourceNames, ComplexKeysShardingValue<Long> complexKeysShardingValue) {
// 得到每个分片健对应的值
Collection<Long> userIdValues = this.getShardingValue(complexKeysShardingValue, "userid");
Collection<Long> idValues = this.getShardingValue(complexKeysShardingValue, "id");
List<String> shardingSuffix = new ArrayList<>();
// 对两个分片健取模的方式:t_order_0_0、t_order_0_1、t_order_1_0、t_order_1_1
for (Long userId : userIdValues) {
for (Long id : idValues) {
String suffix = userId % 2 + "_" + id % 2;
for (String databaseName : dataSourceNames) {
if (databaseName.endsWith(suffix)) {
shardingSuffix.add(databaseName);
}
}
}
}
return shardingSuffix;
}
/**
* shardingValue 分片属性
* logicTableName 逻辑表名
* columnNameAndShardingValuesMap 存储多个分片健
* key 分片key,userid和id
* value 分片value
*/
private Collection<Long> getShardingValue(ComplexKeysShardingValue<Long> shardingValues, final String key) {
Collection<Long> valueSet = new ArrayList<>();
Map<String, Collection<Long>> columnNameAndShardingValuesMap = shardingValues.getColumnNameAndShardingValuesMap();
if (columnNameAndShardingValuesMap.containsKey(key)) {
valueSet.addAll(columnNameAndShardingValuesMap.get(key));
}
return valueSet;
}
}
然后修改配置文件application.properties
,注释掉其他策略,仅保留数据节点并指定复合分片算法
。
spring.application.name=mysql-sharding-jdbc
server.port=8080
# 打印执行的数据库以及语句
spring.shardingsphere.props.sql.show=true
# 数据源
spring.shardingsphere.datasource.names=ds0,ds1,ds2
# 第一个数据源
spring.shardingsphere.datasource.ds0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds0.jdbc-url=jdbc:mysql://172.16.185.176:3306/itechthink_order_0?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
spring.shardingsphere.datasource.ds0.username=root
spring.shardingsphere.datasource.ds0.password=123456
# 第二个数据源
spring.shardingsphere.datasource.ds1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds1.jdbc-url=jdbc:mysql://172.16.185.176:3306/itechthink_order_1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
spring.shardingsphere.datasource.ds1.username=root
spring.shardingsphere.datasource.ds1.password=123456
# 第三个数据源
spring.shardingsphere.datasource.ds2.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds2.jdbc-url=jdbc:mysql://172.16.185.176:3306/itechthink_order_2?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
spring.shardingsphere.datasource.ds2.username=root
spring.shardingsphere.datasource.ds2.password=123456
# 指定workId
spring.shardingsphere.sharding.tables.t_order.key-generator.props.worker.id=1
# id生成策略
spring.shardingsphere.sharding.tables.t_order.key-generator.column=id
spring.shardingsphere.sharding.tables.t_order.key-generator.type=SNOWFLAKE
# 指定 t_order 表的数据节点
spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=ds0.t_order_$->{0..1},ds1.t_order_$->{0..1},ds2.t_order_$->{0..1}
# 复合分片算法 id 和 userid 同时作为分片健
spring.shardingsphere.sharding.tables.t_order.table-strategy.complex.sharding-columns=userid,id
spring.shardingsphere.sharding.tables.t_order.table-strategy.complex.algorithm-class-name=com.itechthink.strategy.CustomComplexShardingAlgorithm
清除之前所有的测试数据。
> USE itechthink_order_0;
> TRUNCATE TABLE t_order_0;
> TRUNCATE TABLE t_order_1;
> USE itechthink_order_1;
> TRUNCATE TABLE t_order_0;
> TRUNCATE TABLE t_order_1;
> USE itechthink_order_2;
> TRUNCATE TABLE t_order_0;
> TRUNCATE TABLE t_order_1;
最后在ShardingJDBCTest
中增加测试方法testMultiPartitionKeySelect()
。
@Test
public void testMultiPartitionKeySelect() {
orderMapper.selectList(new QueryWrapper<Order>().eq("id", 1L).eq("userid", 1L));
}
执行后会报错,因为数据库中并没有t_order_0_0
、t_order_0_1
、t_order_1_0
、t_order_1_1
这四张表,而它们是CustomComplexShardingAlgorithm
类指定要去查询的。
感谢支持
更多内容,请移步《超级个体》。