负载均衡算法

2019-07-24  本文已影响0人  小manong

一、负载均衡算法分类

二、常见负载均衡算法及实现

public interface LoadBalance {
    /**
     * 根据某种策略获取相关服务
     * @return
     */
    Service doPickOneService();
}
public class Service {
    /**
     * 服务名称
     */
    private String name;

    public Service(String name) {
        this.name = name;
    }

    /**
     * 判断服务是否可用,这里假设全部可用
     * @return
     */
    public boolean isAvailable(){
        return true;
    }
}

1、轮询

public class RoundLoaderBalancer implements LoadBalance {

    private static AtomicInteger idx = new AtomicInteger(0);
    @Override
    public Service doPickOneService() {
        List<Service> serviceList = getServiceList();
        int index = getNextNonNegative();
        for (int i = 0; i < serviceList.size(); i++) {
            //获取服务
            Service service = serviceList.get((i + index) % serviceList.size());
            //判断服务是否可用
            if (service.isAvailable()) {
                return service;
            }
        }
        return null;
    }

    /**
     * 假设有这么一个获取全部服务的列表
     *
     * @return
     */
    public List<Service> getServiceList() {
        List<Service> serviceList = new ArrayList<>();
        Service service0 = new Service("service0");
        Service service1 = new Service("service1");
        Service service2 = new Service("service2");
        Service service3 = new Service("service3");
        Service service4 = new Service("service4");
        Service service5 = new Service("service5");
        serviceList.add(service0);
        serviceList.add(service1);
        serviceList.add(service2);
        serviceList.add(service3);
        serviceList.add(service4);
        return serviceList;
    }

    private int getNextNonNegative() {
        return getNonNegative(idx.incrementAndGet());
    }

    /**
     * 通过二进制位操作将originValue转化为非负数:
     * 0和正数返回本身
     * 负数通过二进制首位取反转化为正数或0(Integer.MIN_VALUE将转换为0)
     * return non-negative int value of originValue
     *
     * @param originValue
     * @return positive int
     */
    public int getNonNegative(int originValue) {
        return 0x7fffffff & originValue;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 20; i++) {
            System.out.println(new RoundLoaderBalancer().doPickOneService().toString());
        }
    }
}
- 缺点:无法根据服务器的状态差异进行任务分配的问题。

2、加权轮询算法

3、负载最低优先(可以从连接数、http请求数、cpu负载等情况来)

4、Hash 类算法

负载均衡系统根据任务中的某些关键信息进行 Hash 运算,将相同 Hash 值的请求分配到同一台服务器上,这样做的目的主要是为了满足特定的业务需求。例如:
(1)源地址 Hash
将来源于同一个源 IP 地址的任务分配给同一个服务器进行处理,适合于存在事务、会话的业务。
(2)ID Hash
将某个 ID 标识的业务分配到同一个服务器中进行处理,这里的 ID 一般是临时性数据的 ID(如 session id)。
(3)一致性hash
一致性hash算法,是通过某个hash函数,把同一个来源的请求都映射到同一个节点上。一致性hash算法最大的特点就是同一个来源的请求,只会映射到同一个节点上,可以说是具有记忆功能。只有当这个节点不可用时,请求才会被分配到相邻的可用节点上。

三、常用负载均衡算法应用场景

四、实际案例分析

问题:微信抢红包的高并发架构,应该采取什么样的负载均衡算法?
思考:

微信抢红包架构应该至少包含两个负载均衡,一个是应用服务器的负载均衡,用于将任务请求分发到不同应用服务器,这里可以采用轮询或加权轮询的算法,因为这种速度快,适合抢红包的业务场景;另一起负载均衡是数据服务器的负载均衡,这里更适合根据红包ID进行hash负载均衡,将所有数据请求在同一台服务器上进行,防止多台服务器间的不同步问题。具体:
首先,发红包使用加权轮询,简单适用,成功后返回红包ID给客户端。
其次,抢红包,查询红包都带着ID给服务端,根据ID计算HASH,再利用一致性hash算法,找到最近的一个结点提供服务。

上一篇 下一篇

猜你喜欢

热点阅读