欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-03-26 17:13:18
随机算法是指:从服务器列表中,随机选取一台服务器进行访问。由概率论可以得知,随着客户端调用服务端的次数增多,其实际效果趋近于平均分配请求到服务端的每一台服务器,也就是达到轮询的效果。一、算法描述假设有 N 台服务器 S = {S0, S1, S2, …, Sn},算法可以描述为:1、通过随机函数生成 0 到 N 之间的任意整理,将该数字作为索引,从 S 中获取对应的服务器;假定我们现在有如下四台服务器:服务器地址权重192.168.1.11192.168.1.2...

随机算法是指:从服务器列表中,随机选取一台服务器进行访问。由概率论可以得知,随着客户端调用服务端的次数增多,其实际效果趋近于平均分配请求到服务端的每一台服务器,也就是达到轮询的效果。

一、算法描述

假设有 N 台服务器 S = {S0, S1, S2, …, Sn},算法可以描述为:
1、通过随机函数生成 0 到 N 之间的任意整理,将该数字作为索引,从 S 中获取对应的服务器;

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

服务器地址 权重
192.168.1.1 1
192.168.1.2 2
192.168.1.3 3
192.168.1.4 4

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

服务器地址 序号
192.168.1.1 1
192.168.1.2 2
192.168.1.2 3
192.168.1.3 4

随机算法与服务器权重没有关系,每个服务器会被随机访问到。当调用次数足够多时,每台服务器被访问的概率近似是相等的,随机算法的效果就越趋近于轮询算法。

二、java代码实现

package com.test.mvp.schedulealgothrim;

import com.google.common.collect.SortedMultiset;
import com.google.common.collect.TreeMultiset;
import org.apache.commons.collections4.CollectionUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.TreeMap;

class Server implements Serializable {
    private static final long serialVersionUID = 7246747589293111189L;

    private String server;
    private Integer weight;
    private String description;

    public Server(String server, String description, Integer weight) {
        this.server = server;
        this.description = description;
        this.weight = weight;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }


    public String getServer() {
        return server;
    }

    public void setServer(String server) {
        this.server = server;
    }

    public Integer getWeight() {
        return weight;
    }

    public void setWeight(Integer weight) {
        this.weight = weight;
    }
}

class ServerManager {
    public static Map<String, Server> serverMap = new TreeMap<>();

    static {
        serverMap.put("192.168.1.1", new Server("192.168.1.1", "第1台server", 1));
        serverMap.put("192.168.1.2", new Server("192.168.1.2", "第2台server", 2));
        serverMap.put("192.168.1.3", new Server("192.168.1.3", "第3台server", 3));
        serverMap.put("192.168.1.4", new Server("192.168.1.4", "第4台server", 4));
    }
}

class RandomBalance {
    private static final Random RANDOM = new Random();
    private static ArrayList<String> middleServerList;

    public static String getServer() {
        if (CollectionUtils.isEmpty(middleServerList)) {
            Set<String> serverSet = ServerManager.serverMap.keySet();
            middleServerList = new ArrayList<>(serverSet);
        }

        return middleServerList.get(RANDOM.nextInt(middleServerList.size()));
    }
}

public class RandomScheduleTest {
    public static void main(String[] args) {
        SortedMultiset<String> serverSet = TreeMultiset.create();
        for (int i = 0; i < 100; i++) {
            String server = RandomBalance.getServer();
            Server curServer = ServerManager.serverMap.get(server);
            System.out.println(server + ", " + curServer.getDescription());
            serverSet.add(server, 1);
        }

        ServerManager.serverMap.forEach((key, value)->{
            System.out.println(key + ", count:" + serverSet.count(key));
        });
    }
}

运算结果如下所示:

192.168.1.4, 第4台server
192.168.1.3, 第3台server
192.168.1.1, 第1台server
192.168.1.1, 第1台server
192.168.1.2, 第2台server
192.168.1.2, 第2台server
192.168.1.3, 第3台server
192.168.1.1, 第1台server
192.168.1.2, 第2台server
192.168.1.4, 第4台server
192.168.1.4, 第4台server
192.168.1.1, 第1台server
192.168.1.4, 第4台server
192.168.1.3, 第3台server
192.168.1.4, 第4台server
192.168.1.4, 第4台server
192.168.1.4, 第4台server
192.168.1.4, 第4台server
192.168.1.3, 第3台server
192.168.1.4, 第4台server
192.168.1.4, 第4台server
192.168.1.4, 第4台server
192.168.1.3, 第3台server
192.168.1.3, 第3台server
192.168.1.3, 第3台server
192.168.1.1, 第1台server
192.168.1.2, 第2台server
192.168.1.2, 第2台server
192.168.1.1, 第1台server
192.168.1.4, 第4台server
192.168.1.2, 第2台server
192.168.1.4, 第4台server
192.168.1.2, 第2台server
192.168.1.1, 第1台server
192.168.1.4, 第4台server
192.168.1.4, 第4台server
192.168.1.1, 第1台server
192.168.1.2, 第2台server
192.168.1.2, 第2台server
192.168.1.3, 第3台server
192.168.1.1, 第1台server
192.168.1.1, 第1台server
192.168.1.1, 第1台server
192.168.1.4, 第4台server
192.168.1.2, 第2台server
192.168.1.4, 第4台server
192.168.1.2, 第2台server
192.168.1.2, 第2台server
192.168.1.1, 第1台server
192.168.1.3, 第3台server
192.168.1.3, 第3台server
192.168.1.3, 第3台server
192.168.1.2, 第2台server
192.168.1.3, 第3台server
192.168.1.4, 第4台server
192.168.1.3, 第3台server
192.168.1.1, 第1台server
192.168.1.1, 第1台server
192.168.1.3, 第3台server
192.168.1.4, 第4台server
192.168.1.3, 第3台server
192.168.1.3, 第3台server
192.168.1.1, 第1台server
192.168.1.3, 第3台server
192.168.1.1, 第1台server
192.168.1.4, 第4台server
192.168.1.1, 第1台server
192.168.1.4, 第4台server
192.168.1.3, 第3台server
192.168.1.1, 第1台server
192.168.1.2, 第2台server
192.168.1.2, 第2台server
192.168.1.4, 第4台server
192.168.1.1, 第1台server
192.168.1.3, 第3台server
192.168.1.3, 第3台server
192.168.1.2, 第2台server
192.168.1.3, 第3台server
192.168.1.4, 第4台server
192.168.1.2, 第2台server
192.168.1.1, 第1台server
192.168.1.3, 第3台server
192.168.1.2, 第2台server
192.168.1.1, 第1台server
192.168.1.3, 第3台server
192.168.1.4, 第4台server
192.168.1.1, 第1台server
192.168.1.1, 第1台server
192.168.1.3, 第3台server
192.168.1.1, 第1台server
192.168.1.4, 第4台server
192.168.1.3, 第3台server
192.168.1.4, 第4台server
192.168.1.2, 第2台server
192.168.1.1, 第1台server
192.168.1.2, 第2台server
192.168.1.4, 第4台server
192.168.1.4, 第4台server
192.168.1.1, 第1台server
192.168.1.3, 第3台server
192.168.1.1, count:26
192.168.1.2, count:20
192.168.1.3, count:26
192.168.1.4, count:28

说明:

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

本文地址:https://blog.csdn.net/chinawangfei/article/details/109643598