shardingsphere-jdbc之complex分片(4.1.1)

complex复合分片:基于多个字段进行数据分片。

PS:当前案例根据区域和时间双维度进行分片。

yml

        t_user_activity:
          actualDataNodes: ds0.t_user_activity_south_$->{['2022_0103','2022_0406','2022_0709','2022_1012']},ds0.t_user_activity_north_$->{['2022_0103','2022_0406','2022_0709','2022_1012']}
          tableStrategy:
            #复合条件分片--》多字段分片,字段之间以逗号隔开,PS:不止两个字段,多个也可以
            complex:
              shardingColumns: area,create_date
              algorithmClassName: com.example.skywalkingtest.config.sharding.AreaAndMonthComplexKeysShardingAlgorithm

自定义算法: 

import cn.hutool.core.collection.CollectionUtil;
import com.example.skywalkingtest.utils.DateUtils;
import com.google.common.collect.Range;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingValue;

import java.util.*;


/**
 * 4.1version 复合分片
 */

@Slf4j
public class AreaAndMonthComplexKeysShardingAlgorithm implements ComplexKeysShardingAlgorithm<String> {
    static String tableNamePre = "t_user_activity_";
    static Map<String, List<String>>areaMap;
    static Map<String, List<String>>monthMap;
    static {
        areaMap = new HashMap<String, List<String>>(){{
            put("north",new LinkedList<String>(){{add("天津");add("北京");add("西安");add("咸阳");}});
            put("south",new LinkedList<String>(){{add("苏州");add("南京");add("上海");add("杭州");}});
        }};
        monthMap = new HashMap<String,List<String>>(){{
            put("2022_0103",new LinkedList<String>(){{add("2022_01");add("2022_02");add("2022_03");}});
            put("2022_0406",new LinkedList<String>(){{add("2022_04");add("2022_05");add("2022_06");}});
            put("2022_0709",new LinkedList<String>(){{add("2022_07");add("2022_08");add("2022_09");}});
            put("2022_1012",new LinkedList<String>(){{add("2022_10");add("2022_11");add("2022_12");}});
        }};
    }

    @Override
    public Collection<String> doSharding(Collection<String> collection, ComplexKeysShardingValue<String> complexKeysShardingValue) {
        log.info("collection:{},complexKeysShardingValue:{}",collection,complexKeysShardingValue);
        List<String> areas = new ArrayList<>();
        List<String> months = new ArrayList<>();
        Map<String, Collection<String>> columnNameAndShardingValuesMap = complexKeysShardingValue.getColumnNameAndShardingValuesMap();
        if(CollectionUtil.isNotEmpty(columnNameAndShardingValuesMap)){
            Iterator<Map.Entry<String, Collection<String>>> iterator = columnNameAndShardingValuesMap.entrySet().iterator();
            //筛选出需要拼接的数据信息
            while (iterator.hasNext()){
                Map.Entry<String, Collection<String>> next = iterator.next();
                String key = next.getKey();
                Collection<String> value = next.getValue();
                switch (key){
                    case "area":
                        areas.addAll(this.dataHandler(areaMap,value));
                        break;
                    case "create_date":
                        try {
                            List<String> cllectionValue = new ArrayList<>(value.size());
                            Iterator<String> it = value.iterator();
                            while (it.hasNext()){
                                String next1 = it.next();
                                Date date = DateUtils.strToDateForyyyy_MM_dd(next1);
                                String s = DateUtils.dateToStrForyyyy_MM(date);
                                cllectionValue.add(s);
                            }
                            months.addAll(this.dataHandler(monthMap,cllectionValue));
                        }catch (Exception e){
                            log.info("exception:{}",e);
                        }
                        break;
                    default:
                        break;
                }
            }
        }
        Map<String, Range<String>> columnNameAndRangeValuesMap = complexKeysShardingValue.getColumnNameAndRangeValuesMap();
        if(CollectionUtil.isNotEmpty(columnNameAndRangeValuesMap)){
            Iterator<Map.Entry<String, Range<String>>> rangeIterator = columnNameAndRangeValuesMap.entrySet().iterator();
            //筛选出需要拼接的数据信息
            while (rangeIterator.hasNext()){
                Map.Entry<String, Range<String>> next = rangeIterator.next();
                String key = next.getKey();
                Range<String> value = next.getValue();
                Map<String,String> map = new HashMap<String,String>();
                switch (key){
                    case "area":
                        map.put("lowerEndpoint",value.lowerEndpoint());
                        map.put("upperEndpoint",value.upperEndpoint());
                        areas.addAll(this.rangeDataHandler(areaMap,map));
                        break;
                    case "create_date":
                        try {
                            Date date = DateUtils.strToDateForyyyy_MM_dd(value.lowerEndpoint());
                            String lowerEndpoint = DateUtils.dateToStrForyyyy_MM(date);
                            Date date1 = DateUtils.strToDateForyyyy_MM_dd(value.upperEndpoint());
                            String upperEndpoint = DateUtils.dateToStrForyyyy_MM(date1);
                            map.put("lowerEndpoint",lowerEndpoint);
                            map.put("upperEndpoint",upperEndpoint);
                            months.addAll(this.rangeDataHandler(monthMap,map));
                        }catch (Exception e){
                            log.info("exception:{}",e);
                        }
                        break;
                    default:
                        break;
                }
            }
        }
        Set<String> tableNames = new HashSet<>();
        
/**
         * todo 组装要路由的表
         *  没有区域信息==>全区域查询,有区域信息==>指定区域查询
         *  没有时间范围==>全年查询,有时间范围==>指定时间查询
         */

        Collection<String> areaCollection = CollectionUtil.isEmpty(areas)?areaMap.keySet():areas;
        Collection<String> monthCollection = CollectionUtil.isEmpty(months)?monthMap.keySet():months;
        for (String k : areaCollection) {
            String sb = new StringBuilder(tableNamePre).append(k).append("_").toString();
            for (String m : monthCollection) {
                tableNames.add(new StringBuilder(sb).append(m).toString());
            }
        }
        return tableNames;
    }

    public List<String> dataHandler(Map<String, List<String>> map,Collection<String> value){
        List<String> list = new LinkedList<>();
        for (String k : map.keySet()) {
            List<String> v = map.get(k);
            long count = v.stream().filter(o -> value.contains(o)).count();
            if(count>0)
                list.add(k);
        }
        return list;
    }

    public List<String> rangeDataHandler(Map<String, List<String>> map,Map<String,String> mapRange){
        String upperEndpoint = mapRange.get("upperEndpoint");
        String lowerEndpoint = mapRange.get("lowerEndpoint");
        List<String> list = new LinkedList<>();
        for (String k : map.keySet()) {
            List<String> v = map.get(k);
            long count = v.stream().filter(o -> upperEndpoint.equalsIgnoreCase(o)||lowerEndpoint.equalsIgnoreCase(o)).count();
            if(count>0)
                list.add(k);
        }
        return list;
    }
}

表结构: 

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.io.Serializable;
import java.util.Date;

/**
 * 用户参与活动记录
 */
@Data
@TableName("t_user_activity")
public class UserActivityRecordPo implements Serializable {
    @TableId(value = "id",type = IdType.AUTO)
    private Long id;
    @TableField(value = "area")
    private String area;
    @TableField(value = "user_name")
    private String userName;
    @TableField(value = "create_date")
    private String createDate;
    @TableField(value = "activity_id")
    private Long activityId;
    @TableField(value = "activity_name")
    private String activityName;
    @TableField(value = "scope")
    private Integer scope;
}

 测试:

@Test
    void insertUserActivityRecordDemo(){
        Date date = DateUtils.strToDateForyyyy_MM_dd("2022-03-01");
        userActivityMapper.insert(new UserActivityRecordPo("上海","jack","2022-03-01",1l,"生活常识竞赛",85));
        userActivityMapper.insert(new UserActivityRecordPo("苏州","jack","2022-05-01",1l,"生活常识竞赛",85));
        userActivityMapper.insert(new UserActivityRecordPo("南京","jack","2022-04-01",1l,"生活常识竞赛",85));
        userActivityMapper.insert(new UserActivityRecordPo("杭州","jack","2022-07-01",1l,"生活常识竞赛",85));
        userActivityMapper.insert(new UserActivityRecordPo("上海","jack","2022-12-01",1l,"生活常识竞赛",85));
        userActivityMapper.insert(new UserActivityRecordPo("上海","jack","2022-09-01",1l,"生活常识竞赛",85));
        userActivityMapper.insert(new UserActivityRecordPo("北京","jack","2022-03-01",1l,"生活常识竞赛",85));
        userActivityMapper.insert(new UserActivityRecordPo("天津","jack","2022-05-01",1l,"生活常识竞赛",85));
        userActivityMapper.insert(new UserActivityRecordPo("西安","jack","2022-06-01",1l,"生活常识竞赛",85));
        userActivityMapper.insert(new UserActivityRecordPo("咸阳","jack","2022-07-01",1l,"生活常识竞赛",85));
    }

    @Test
    void queryUserActivityDemo(){
        List<UserActivityRecordPo> list = userActivityMapper.selectList(new LambdaQueryWrapper<UserActivityRecordPo>()
                .between(UserActivityRecordPo::getCreateDate,"2022-04-01","2022-08-01")
                .in(UserActivityRecordPo::getArea,new ArrayList<String>(){{add("咸阳");add("西安");add("上海");}})
                .ge(UserActivityRecordPo::getScope,20));
        System.out.println(list);
    }

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值