[zebra源码]GroupDataSource读库的负载均衡

GroupDataSource的物理结构


image.png

负载均衡的对象

zebra的负载均衡是在GroupDataSource的读库 readDataSource( LoadBalanceDataSource) 中进行的, 它内部包含多个读库节点的SingleDataSource

LoadBalanceDataSource#getConnection() -> router.select(context);

关键对象DataSourceRouter 数据源路由器

负载均衡由 DataSourceRouter 数据源路由器实现具体的逻辑 => 它是个套娃

image.png

包含 中心路由、idc路由、区域路由和权重, 这几个负载均衡算法是嵌套执行的, 从范围大到小逐层进行

默认的 routerStrategy=“WeightRouter" 即 WeightDataSourceRouter 在最里层同机房范围内的多个读库是根据权重来选择的


image.png

了解更多,官方文档 zebra路由设计

区域、中心、机房,最后都会走向基于权重的路由 WeightDataSourceRouter#select()

public RouterTarget select(Set excludeTargets) {
    if (!this.targets.isEmpty()) {
        TreeSet weights = this.targets;
        int tmpGroupDataSourceTargetSize = this.groupDataSourceTargetSize;

        if (excludeTargets != null && !excludeTargets.isEmpty()) {
            // 需要排除某些GroupDataSourceTarget的话,就重新copy一个weights
            TreeSet copyWeights = new TreeSet();
            tmpGroupDataSourceTargetSize = 0;
            for (RouterTarget routerTarget : weights) {
                if (excludeTargets.contains(routerTarget)) {
                    continue;
                }
                // 先将节点先放入到排序集合中
                // 假设  节点1 -> weight=2, 节点2 -> weight=3
                // 则在排序树中 节点1 -> sort=2, 节点2 -> sort = 2+3
                int weight = routerTarget.getWeight();
                tmpGroupDataSourceTargetSize += weight;
                copyWeights.add(new RouterTarget(routerTarget.getId(), weight, tmpGroupDataSourceTargetSize - 1));
            }
            weights = copyWeights;
        }

        if (weights.isEmpty() || tmpGroupDataSourceTargetSize <= 0) {
            return null;
        }
        // 取一个随机数
        int randomNum = random.nextInt(tmpGroupDataSourceTargetSize);
        RouterTarget tempForSearch = new RouterTarget(null, -1, randomNum);
        //排序集合中最靠近随机数的entry则为目标节点
        return weights.ceiling(tempForSearch);
    } else {
        return null;
    }
}
}

想要查看具体执行细节 ,可以debug 源码里 com.dianping.zebra.group.router 包下的 DataSourceRouter 单测

你可能感兴趣的:([zebra源码]GroupDataSource读库的负载均衡)