Shardingjdbc复合分片算法complex的使用配置方式详解与说明(三)

shardingsphere复合分片的配置详解:

特点:
1、复合分片比较灵活,适合于分片的字段比较多,分片比较复杂的场景,使用这种分片的话必须对自己的业务比较明确,
另外如果是分片的字段类型不是同一种的类型的话(如果一个userId Long类型、一个userName String类型),要自己在分片算法中处理,
如果是业务比较简单还是使用标准分片更简单一点,配置起来也更方便。为什么这么说呢?因为比如你的分片字段是两个那么如果你值传递一个分片的字段作为
查询条件的话如果分片算法设计的不好的话那就很可能只能全局查询了
2、支持 SQL 语句中有>,>=, <=,<,=,IN 和 BETWEEN AND 等操作符

复合分片的配置举例:

#一下是使用分库分表 多字段 分库分表
#打印sql
spring.shardingsphere.props.sql-show=true
#数据库的分库策略
spring.shardingsphere.rules.sharding.tables.m_user.database-strategy.complex.sharding-columns=buMen,sex
spring.shardingsphere.rules.sharding.tables.m_user.database-strategy.complex.sharding-algorithm-name=complex-db
# 配置具体的分库规则(分库的字段+分库的算法=分库规则)这里是使用HASH_MOD的算法
spring.shardingsphere.rules.sharding.sharding-algorithms.complex-db.type=CLASS_BASED
#策略的名称 complex 时必选
spring.shardingsphere.rules.sharding.sharding-algorithms.complex-db.props.strategy=complex
#算法名称 complex 时必选
spring.shardingsphere.rules.sharding.sharding-algorithms.complex-db.props.algorithmClassName=com.shardings.selfdefined.MyComplexShardingAlgorithmDB

#lcg_user表的分表的策略
spring.shardingsphere.rules.sharding.tables.m_user.actual-data-nodes=d$->{0..1}.m_user_$->{0..1}
#配置表的分片算法
spring.shardingsphere.rules.sharding.tables.m_user.table-strategy.complex.sharding-columns=id,userName
#这里的算法名称自己随便取
spring.shardingsphere.rules.sharding.tables.m_user.table-strategy.complex.sharding-algorithm-name=complex-tb

#配置具体的分表的算法-使用MOD,这时候一般是使用INLINE表达式
spring.shardingsphere.rules.sharding.sharding-algorithms.complex-tb.type=CLASS_BASED
#配置策略
spring.shardingsphere.rules.sharding.sharding-algorithms.complex-tb.props.strategy=complex
#配置算法的全限定名称
spring.shardingsphere.rules.sharding.sharding-algorithms.complex-tb.props.algorithmClassName=com.shardings.selfdefined.MyComplexShardingAlgorithmTB

# 配置lcg_user的id采用雪花算法生成全局id策略
spring.shardingsphere.rules.sharding.tables.m_user.key-generate-strategy.column=id
spring.shardingsphere.rules.sharding.tables.m_user.key-generate-strategy.key-generator-name=SNOWFLAKE

实现复合分片的算法接口ComplexKeysShardingAlgorithm 该接口的泛型表示的是分片的字段的类型

代码举例:
数据库分片的算法:

package com.shardings.selfdefined;

import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.sharding.api.sharding.complex.ComplexKeysShardingAlgorithm;
import org.apache.shardingsphere.sharding.api.sharding.complex.ComplexKeysShardingValue;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;

/**
* @author: LCG
* @date: 2022-11-12 18:52:43
* @description: 自定义 多字段分片算法 按照数据库划分
**/
@Slf4j
public class MyComplexShardingAlgorithmDB implements ComplexKeysShardingAlgorithm<String> {

    private static final String column1="buMen";

    private static final String column2="sex";

    /**
     * @author: LCG
     * @date: 2022-11-12 23:19:16
     * @description:  collection  数据库的逻辑名称集合
     *                complexKeysShardingValue  复合分片字段的字段名和字段值
     */
    @Override
    public Collection<String> doSharding(Collection<String> collection, ComplexKeysShardingValue<String> complexKeysShardingValue) {

        String logicTableName = complexKeysShardingValue.getLogicTableName();
        //等于号   in 的值
        Map<String, Collection<String>> columnNameAndShardingValuesMap = complexKeysShardingValue.getColumnNameAndShardingValuesMap();
        //实现  >,>=, <=,<  和 BETWEEN AND 等操作
        Map columnNameAndRangeValuesMap = complexKeysShardingValue.getColumnNameAndRangeValuesMap();
 
        Collection<String> c1 = columnNameAndShardingValuesMap.get(column1);
        Collection<String> c2 = columnNameAndShardingValuesMap.get(column2);
        if(Optional.ofNullable(c1).isPresent()&&Optional.ofNullable(c2).isPresent()){
            StringBuffer sb=new StringBuffer(c1.stream().findFirst().get());
            sb.append(c2.stream().findFirst().get());
            int i = sb.toString().hashCode() % collection.size();
            String s = i == 0 ? "d0" : "d1";
            return Arrays.asList(s);
        }
        return collection;
    }


    @Override
    public void init() {
    }

    @Override
    public String getType() {
        return "COMPLEX-DB";
    }
}

代码举例:表分片举例:

package com.shardings.selfdefined;

import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.sharding.api.sharding.complex.ComplexKeysShardingAlgorithm;
import org.apache.shardingsphere.sharding.api.sharding.complex.ComplexKeysShardingValue;


import java.util.*;

/**
* @author: LCG
* @date: 2022-11-13 14:43:22
* @description: 自定义 多字段分片算法 按照数据表划分 这个是复合分片的算法的自定义分片算法
*               这里的这个泛型是指的是 分片字段的类型
**/
@Slf4j
public class MyComplexShardingAlgorithmTB implements ComplexKeysShardingAlgorithm {

    private static final String col1="id";
    private static final String col2="userName";

    @Override
    public Collection<String> doSharding(Collection collection, ComplexKeysShardingValue complexKeysShardingValue) {
        String logicTableName = complexKeysShardingValue.getLogicTableName();

        //等于号   in 的值
        Map columnNameAndShardingValuesMap = complexKeysShardingValue.getColumnNameAndShardingValuesMap();
        
        实现  >,>=, <=,<  和 BETWEEN AND 等操作 的值 大家需要根据这里边的值 自己给出算法计算应该返回的数据表名称
        Map columnNameAndRangeValuesMap = complexKeysShardingValue.getColumnNameAndRangeValuesMap();

        List c1Id = (List) columnNameAndShardingValuesMap.get(col1);
        List c2UserName = (List) columnNameAndShardingValuesMap.get(col2);
        if(Optional.ofNullable(c1Id).isPresent()||Optional.ofNullable(c2UserName).isPresent()){
            StringBuffer sb=new StringBuffer(c1Id.get(0).toString());
            sb.append(c2UserName.get(0));
            int i = (sb.toString().hashCode()& Integer.MAX_VALUE) % collection.size();
            log.info("======余数==={}======id={}=userName={}",i,c1Id,c2UserName);
            Object[] stt=new Object[collection.size()];
            Object[] strings = collection.toArray(stt);
            stt=null;
            return Arrays.asList(strings[i].toString());
        }
        log.info("没有得到合适的分片结果=:表名{},参数:{}",collection,columnNameAndShardingValuesMap);
        throw new RuntimeException("没有得到合适的分片结果");
    }

    @Override
    public void init() {
    }

    @Override
    public String getType() {
        return null;
    }

}

版权声明:本文为licigao原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。