一致性哈希实现负载均衡

一致性哈希实现负载均衡

1 为什么需要哈希算法

解决同一个用户访问服务器是,访问的是不同的服务器的问题

场景:集群造成的session没有同步

当一个用户访问服务器A的时候,该台服务器A会保存这台服务器的session,但是当下次再访问的时候,被负载均衡算法可能算到了不同的服务器B,服务器B中没有用户的session,会要求用户再次登录。

解决:

  1. 加入redis,将session存到redis中
  2. Tomcat同步session
  3. 一致性哈希算法

2 什么是一致性哈希算法

服务器集群接收到一次请求调用时,可以根据请求的信息,比如客户端的ip地址,或请求路径与请求参数等信息进行哈希,可以得出一个哈希值,特点是对于相同的ip地址,或请求路径和请求参数哈希出来的值是一样的,只要能再增加一个算法,能够把这个哈希值映射成一个服务端ip地址,就可以使用相同的请求(相同的ip地址,或请求路径和请求参数)落到同一服务器上。

因为客户端发起的请求是无穷无尽的(客户端地址不同,请求参数不同等等),所以对于的哈希值也是无穷大的,所以我们不能把所有的哈希值都进行映射到服务端ip上,所有这里需要用到哈希环

3 虚拟节点

  1. 解决一个服务器挂掉造成的服务不均匀问题
  2. 使得哈希环更加平滑

当时当一台服务器挂掉的话,会造成服务器服务不均匀的情况

会发现,ip3和ip1直接的范围是比较大的,会有更多的请求落到ip1上,这是“不公平”,解决这个问题需要加入虚拟节点,比如:

其中,ip2-1,ip3-1就是虚拟节点,并不能处理节点,而是等同于对应的服务器。
实际上,这只是处理这种不均衡性的一种思路,实际上就算哈希环本身是均衡的,你也可以增加更多的虚拟节点来使得这个环更加的平滑

上面的哈希环更加的散列,平滑

只需要找到大于hashcode的以一个虚拟节点即可

由于哈希环上的点是有序的,那么采用的数据结构是TreeMap

4 代码实现

public class ServerIps {

    public static final List<String> LIST = (List<String>) Arrays.asList(
            "192.168.0.1",
            "192.168.0.2",
            "192.168.0.3",
            "192.168.0.4",
            "192.168.0.5",
            "192.168.0.6",
            "192.168.0.7",
            "192.168.0.8",
            "192.168.0.9",
            "192.168.0.10"
            );

}

======================================

import java.util.SortedMap;
import java.util.TreeMap;

public class ConsistentHash {

    private static TreeMap<Integer, String> virtualNodes = new TreeMap<>();
    private static final int VIRTUAL_NODES = 160;

    static {
        for(String ip: ServerIps.LIST) {
            for (int i = 0; i < VIRTUAL_NODES; i++) {
                int hash = getHash(ip+i);
                virtualNodes.put(hash, ip);
            }

        }
    }

    private static String getServer(String client) {
        int hash = getHash(client);

        //大于hash,virtualNodes的子树的firstkey
        //tailMap,能获得大于等于hash值的一棵子红黑树
        SortedMap subMap = virtualNodes.tailMap(hash);
        Integer firstKey = null;

        if(subMap == null) {
            firstKey = virtualNodes.firstKey();
        } else {
            firstKey = (Integer) subMap.firstKey();
        }

        return virtualNodes.get(firstKey);
    }

    private static int getHash(String str) {
        final int p = 16777619;
        int hash = (int) 2166136261L;
        for(int i = 0; i < str.length(); i++)
            hash = (hash ^ str.charAt(i)) * p;
        hash += hash << 13;
        hash ^= hash >> 7;
        hash += hash << 3;
        hash ^= hash >> 17;
        hash += hash << 5;

        if(hash < 0)
            hash = Math.abs(hash);
        return hash;
    }

    public static void main(String[] args) {

        for (int i = 0; i < 12; i++) {
            System.out.println(getServer("client"+i));
        }
    }

}

5 最小活跃数

由于服务的时间并不是固定,如果平均分配服务器有的时候并不合理

比如:
有3个消息,分别请求了A、B、C三台服务器,处理的时间依次为3s、2s、1s,当1s后有一个新的请求过来,按道理说应该A服务器来服务,但是C台服务器已经空闲了,所有这样的分配方式有时候并不合理。

解决:
采用最小活跃数,哪台机器服务最少,用哪台机器,当都大致相等的时候可以根据前面的随机、轮询等。

6 算法的魅力

  • 将程序“复杂化”,提升程序效率到极致

原文地址:https://www.cnblogs.com/Stephanie-boke/p/12293626.html

时间: 2024-11-18 04:11:49

一致性哈希实现负载均衡的相关文章

应用负载均衡(轮询&&一致性哈希)

今天看书看到了应用负载均衡的轮询与一致性哈希,其中说到,一致性哈希可以根据应用请求的URL或者URL参数将系统的请求转发到同一节点,而轮询是将请求均匀地转发到每个服务器. 1.轮询: 优点:到后端应用的请求更加均匀,使得每个服务器基本均衡 缺点:随着后端应用服务器的增加,缓存的命中率为下降,这种方式不会因为热点问题导致其中某一台 服务器负载过重 2.一致性哈希 优点:相同的请求会转发到同一台服务器,命中率不会因为增加服务器而下降 缺点:因为相同的请求会转发到同一服务器,可能会导致某台服务器负载过

Nginx的负载均衡方案详解

Nginx的负载均衡方案详解 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs Nginx的负载均衡方案有: 1.轮询 轮询即Round Robin,根据Nginx配置文件中的顺序,依次把客户端的Web请求分发到不同的后端服务器. 配置的例子如下: http{ upstream sampleapp { server <<dns entry or IP Address(optional with port)>>; server <&l

【Nginx】配置Nginx的负载均衡

阅读目录 参考的优秀文章 在本机运行2个Tomcat Nginx的负载均衡配置 参考的优秀文章 tomcat配置文件server.xml详解 AJP协议总结与分析 Using nginx as HTTP load balancer 在本机运行2个Tomcat 现需要运行两个Tomcat,监听不同端口,让Nginx作负载均衡跳转过来.Tomcat版本:apache-tomcat-7.0.69-windows-x64.zip 要在一台机器运行两个Tomcat,要解决端口的冲突,我们只需要D:\gre

Nginx负载均衡的四种模式

1.轮询 轮询即Round Robin,根据Nginx配置文件中的顺序,依次把客户端的Web请求分发到不同的后端服务器. 每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除. pstream webapp { server server2; server server1; } 2.最少连接 Web请求会被转发到连接数最少的服务器上.least_conn算法很简单,首选遍历后端集群,比较每个后端的conns/weight,选取该值最小的后端.如果有多个后端的conn

Nginx负载均衡4种方案

1.轮询 轮询即Round Robin,根据Nginx配置文件中的顺序,依次把客户端的Web请求分发到不同的后端服务器. 配置的例子如下:http{     upstream sampleapp {         server <<dns entry or IP Address(optional with port)>>;         server <<another dns entry or IP Address(optional with port)>&

负载均衡(Nginx)使用教程

Nginx实例 //************说明*************// 此文章基于Nginx对多台tomcat服务器进行负载均衡 //************准备工作*************// nginx安装包下载:http://nginx.org/en/download.html nginx在线手册:http://shouce.jb51.net/nginx/index.html tomcat1:8081端口(本地安装启动) tomcat2:8082端口(本地安装启动) tomcat

Nginx负载均衡配置实例(转)

1.轮询 轮询即Round Robin,根据Nginx配置文件中的顺序,依次把客户端的Web请求分发到不同的后端服务器.配置的例子如下: http{ upstream sampleapp { server <<dns entry or IP Address(optional with port)>>; server <<another dns entry or IP Address(optional with port)>>; } .... server{

nginx 的负载均衡四种模式及配置

1.轮询 轮询即Round Robin,根据Nginx配置文件中的顺序,依次把客户端的Web请求分发到不同的后端服务器.配置的例子如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 http{  upstream sampleapp {    server <<dns entry or IP Address(optional with port)>>;    server <<another dns entry or IP Address(optiona

2016 -Nginx的负载均衡 - 一致性哈希 (Consistent Hash)

Nginx版本:1.9.1 算法介绍 当后端是缓存服务器时,经常使用一致性哈希算法来进行负载均衡. 使用一致性哈希的好处在于,增减集群的缓存服务器时,只有少量的缓存会失效,回源量较小. 在nginx+ats / haproxy+squid等CDN架构中,nginx/haproxy所使用的负载均衡算法便是一致性哈希. 我们举个例子来说明一致性哈希的好处. 假设后端集群包含三台缓存服务器,A.B.C. 请求r1.r2落在A上. 请求r3.r4落在B上. 请求r5.r6落在C上. 使用一致性哈希时,当