分库场景下的数据分布治理:基于权重的负载均衡策略

一、需求背景

云服务项目,MySQL水平分库,由于各种历史原因,各个分库的数据量不均衡,新增分库数据量低,需要一种负载均衡算法能自动平衡数据分布

二、解决方案

基于数据库权重的负载均衡算法

bbef1a9ee0ff511ac9f742dec523f7cb.png

三、代码实现

权重存储结构表

26520d5a61354b654e272a487fe8e011.png

定时同步权限信息的任务

d8d7c4e9bdf4201b112d01d11d171555.png

基于权重的负载均衡算法

public class DbKeyWeightDto implements Serializable {


    private static final long serialVersionUID = -5196176232082947951L;


    public DbKeyWeightDto() {
    }


    public DbKeyWeightDto(String dbkey, Integer weight) {
        this.dbkey = dbkey;
        this.weight = weight;
    }


    private String dbkey;


    private Integer weight;


}




public class ByWeight {
    /**
     * 测试
     * @param args
     */
    public static void main(String[] args) {
        ArrayList<DbKeyWeightDto> weightList = getWeightList();
        for (int i = 0; i <10000 ; i++) {
            DbKeyWeightDto dto = selectOne(weightList);
            System.out.println(dto.getDbkey());
        }
    }


    /**
     * 负载均衡算法
     * @param weightList
     * @return
     */
    private static DbKeyWeightDto selectOne(ArrayList<DbKeyWeightDto> weightList) {
        int size = weightList.stream().mapToInt(DbKeyWeightDto::getWeight).sum();
        int[] tempArray = new int[size];
        int i=0;
        for (int i1 = 0; i1 < weightList.size(); i1++) {
            int weight = weightList.get(i1).getWeight();
            for (int j = 0; j <weight ; j++) {
                tempArray[i]=i1;
                i++;
            }
        }
        Random random = new Random();
        return weightList.get(tempArray[random.nextInt(size)]);
    }


    /**
     * 计算权重信息
     * @return
     */
    private static ArrayList<DbKeyWeightDto> getWeightList() {
        //模拟定时任务统计获取分库的企业数量数据
        ArrayList<DbKeyWeightDto> dbKeyWeightDtos = new ArrayList<>();
        Random random = new Random();
        for (int i = 1; i <=4 ; i++) {
            dbKeyWeightDtos.add(new DbKeyWeightDto("dbkey"+i,random.nextInt(100)));
        }
        //排序
        Collections.sort(dbKeyWeightDtos,(a1, a2)->{
            if (a1.getWeight()==null) {
                a1.setWeight(0);
            }
            if (a2.getWeight()==null) {
                a2.setWeight(0);
            }
            return a1.getWeight()-a2.getWeight();
        });
        //首尾权重对调
        for (int i = 0; i < dbKeyWeightDtos.size()/2; i++) {
            Integer temp = dbKeyWeightDtos.get(i).getWeight();
            dbKeyWeightDtos.get(i).setWeight(dbKeyWeightDtos.get(dbKeyWeightDtos.size()-1-i).getWeight());
            dbKeyWeightDtos.get(dbKeyWeightDtos.size()-1-i).setWeight(temp);
        }
        return dbKeyWeightDtos;
    }
}

四、总结

1、定时任务有多种方案,我就不写代码了,知道思路就行了;

2、统计数据量的时候要最终转换为百分比下的相对数量;

3、数据量越大的分库,权重值应该越小,所以要按数据量的百分比排序后,再首尾对调才是正确的权重值;

4、负载均衡算法的思路是:

    1)产生一个数组大小等于各个分库的权重之和(一定要用百分比相对数据量哦,否则数组就太大了);

    2)按权重值给每个分库分配数组格子的数量,格子的内容是list的元素索引;

    3)产生数组大小以内的随机数;

    4)这就选出来了一个list元素索引,可以进一步得到dbkey的值;

5、新增数据库的特殊情况,这时候计算权重信息时注意不能漏掉它,它的初始数据量为0,计算完权重信息后,它的权重值应该是最大的就对了,另外同时数据量最大的那个分库的权重值会是0,这是符合预期的,因为首尾对调的原因。随着新增分库数据的增加,就会慢慢趋于平衡;

6、权重值的计算部分有很多策略和指标可以进行复杂扩展,各位同学要根据自己项目的实际情况使用不同的指标和策略计算权重值;

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吕哥架构

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值