负载均衡算法--加权随机法(Weight Random)

本文深入探讨了加权随机算法在负载均衡中的应用,详细解释了如何根据服务器配置和负载分配权重,通过随机方式选择后端服务器,确保了高并发场景下的服务稳定性和效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

接上一篇博文:负载均衡算法–随机法(Random),本文讲解加权随机算法。

与加权轮询法一样,加权随机法也根据服务器的配置,系统的负载分配不同的权重。不同的是,它是按照权重随机请求后端服务器,而非顺序。

算法描述

假设有 N 台服务器 S = {S0, S1, S2, …, Sn},默认权重为 W = {W0, W1, W2, …, Wn},权重之和为 weightSum, 服务器列表为 serverList,算法可以描述为:
1、初始化 serverList,将 W0 个 S0 加入至serverList,将 W1 个 S1 加入至serverList,依据此规则将所有的服务器加入至 serverList 中;
2、通过随机函数生成 0 到 weightSum 之间的任意整理,将该数字作为索引,从 serverList 中获取对应的服务器;

假定我们现在有如下四台服务器:

服务器地址权重
192.168.1.11
192.168.1.22
192.168.1.33
192.168.1.44

初始化服务列表后, serverList 如下:

服务器地址序号
192.168.1.11
192.168.1.22
192.168.1.23
192.168.1.34
192.168.1.35
192.168.1.36
192.168.1.47
192.168.1.48
192.168.1.49
192.168.1.410

与加权轮询算法类似,根据权重的不同向 serverList 添加相应的服务器,只不过服务器是通过随机算法获取的。

代码实现

1、服务器管理类

package org.learn.loadbalance;

import java.util.Map;
import java.util.TreeMap;

/**
 * @author zhibo
 * @date 2019/5/16 16:25
 */
public class ServerManager {
    public volatile static Map<String, Integer> serverMap = new TreeMap<>();

    static {
        serverMap.put("192.168.1.1", 1);
        serverMap.put("192.168.1.2", 2);
        serverMap.put("192.168.1.3", 3);
        serverMap.put("192.168.1.4", 4);
    }
}

2、加权随机类

package org.learn.loadbalance;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author zhibo
 * @date 2019/5/16 16:28
 */
public class WeightRandom {

    public static String getServer() {
        ArrayList<String> serverList = new ArrayList<>();
        Set<String> serverSet = ServerManager.serverMap.keySet();
        Iterator<String> iterator = serverSet.iterator();

        Integer weightSum = 0;
        while(iterator.hasNext()){
            String server = iterator.next();
            Integer weight = ServerManager.serverMap.get(server);
            weightSum += weight;
            for (int i = 0; i < weight; i++) {
                serverList.add(server);
            }
        }

        Random random = new Random();
        String server = serverList.get(random.nextInt(weightSum));
        return server;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 20; i++) {
            String server = getServer();
            System.out.println(server);
        }
    }
}

1、使用 Random 对象随机生成 [0, serverList.size()) 的整数,然后通过索引获取到服务器。
2、在多线程的情况下, 线程A修改 ServerManager.serverMap 的值,线程B无法即时拿到线程A修改后的值,因此可能会产生请求错误,需要调用端进行容错处理。
3、从宏观的角度讲,访问量越大负载越均衡;微观的角度讲,看起来没有那么均衡。

执行 main 方法输出结果如下:
在这里插入图片描述
文章内容仅代表个人观点,如有不正之处,欢迎批评指正,谢谢大家。

### 存储系统中的负载均衡算法 在分布式存储系统中,为了提高数据访问效率并减少单点过载的风险,通常会采用多种负载均衡策略来分配请求到不同的节点上。以下是几种常见的负载均衡算法以及它们的实现方式: #### 1. 基于哈希的负载均衡算法 该方通过计算键值的哈希函数,将请求映射到特定的目标节点上[^1]。此技术的优点在于其简单性和一致性,在理想情况下可以均匀分布流量。 ```java public class HashLoadBalancer { private List<String> nodes; public HashLoadBalancer(List<String> nodes) { this.nodes = nodes; } public String getNode(String key) { int hash = Math.abs(key.hashCode() % nodes.size()); return nodes.get(hash); } } ``` 上述代码展示了一个基本的基于哈希的负载均衡器实现。它接受一组节点列表作为输入,并根据给定的关键字返回相应的目标节点。 #### 2. 轮询 (Round Robin) 轮询是一种较为直观的方,其中客户端依次向各个可用的服务端发送请求[^3]。这种方能够确保所有的服务实例都得到平等对待,从而达到平衡的效果。 ```java public class RoundRobinLoadBalancer { private final AtomicInteger counter = new AtomicInteger(0); private final List<String> servers; public RoundRobinLoadBalancer(List<String> serverList){ this.servers = serverList; } public synchronized String getNextServer(){ int index = counter.incrementAndGet(); if(index >= Integer.MAX_VALUE || index >= servers.size()){ counter.set(0); // reset when reach limit or end of list } return servers.get(counter.get()%servers.size()); } } ``` 这里提供了一种线程安全版本的轮询调度程序示例,利用`AtomicInteger`类管理计数器状态变化过程。 #### 3. 随机选择(Random Selection) 随机选取某个活动服务器处理下一个连接请求也是一种可行的选择方案之一。尽管这种方式可能无始终维持完美的资源利用率,但在某些场景下仍具有一定的适用价值。 ```java import java.util.Random; public class RandomLoadBalancer{ private static final Random RANDOM=new Random(); public String selectRandomlyFrom(List<String> availableServers){ return availableServers.get(RANDOM.nextInt(availableServers.size())); } } ``` 这段片段定义了一个用于执行随机挑选操作的功能模块——即从传入参数集合里抽取单一成员项供后续调用者使用。 #### 4. 权重基础型(Wighted-based Approach) 考虑到不同机器可能存在性能差异的情况,因此引入加权概念显得尤为重要;具体而言就是赋予那些更强大的设备更高的优先级以便承担更多工作量。 ```java class WeightedNode implements Comparable<WeightedNode>{ double weight; String name; @Override public int compareTo(WeightedNode o){return Double.compare(this.weight,o.weight);} } // Example usage within a weighted round-robin context. public class WeightAwareRRBalancer extends AbstractLBStrategy { Queue<WeightedNode> queue= new PriorityQueue<>(); public void addNodesWithWeights(Map<String,Double> map){ for(var entry :map.entrySet())queue.add(new WeightedNode(entry.getValue(),entry.getKey())); } public Optional<String> nextTarget(){ var top=queue.poll();if(top==null)return empty();else {queue.offer(top);return some(top.name);} } } ``` 以上展示了如何构建支持带权重比较逻辑的数据结构体(如PriorityQueue),并通过调整内部顺序关系影响最终输出结果序列特性。 --- ### 总结 每一种负载均衡机制都有各自的特点与局限性,实际应用过程中需综合考量业务需求、网络环境等因素决定最适合的技术路线图。无论是追求极致公平性的纯数学模型还是灵活性较高的动态适应架构设计思路都可以找到对应的理论支撑材料加以验证优化改进方向。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值