nginx 负载均衡之一致性hash,普通hash

哈希负载均衡原理
  ngx_http_upstream_hash_module支持普通的hash及一致性hash两种负载均衡算法,默认的是普通的hash来进行负载均衡。
  nginx 普通的hash算法支持配置http变量值作为hash值计算的key,通过hash计算得出的hash值和总权重的余数作为挑选server的依据;nginx的一致性hash(chash)算法则要复杂一些。这里会对一致性hash的机制原理作详细的说明。
一致性hash算法的原理
一致性hash用于对hash算法的改进,后端服务器在配置的server的数量发生变化后,同一个upstream server接收到的请求会的数量和server数量变化之间会有变化。尤其是在负载均衡配置的upstream server数量发生增长后,造成产生的请求可能会在后端的upstream server中并不均匀,有的upstream server负载很低,有的upstream server负载较高,这样的负载均衡的效果比较差,可能对upstream server造成不良的影响。由此,产生了一致性hash算法来均衡。
   那么为什么一致性hash算法能改善这种情况呢?这里引用网上资料的一致性hash算法的图例。
因为对于hash(k)的范围在int范围,所以我们将0~2^32作为一个环。其步骤为:
1,求出每个服务器的hash(服务器ip)值,将其配置到一个 0~2^n 的圆环上(n通常取32)。
2,用同样的方法求出待存储对象的主键 hash值,也将其配置到这个圆环上,然后从数据映射到的位置开始顺时针查找,将数据分布到找到的第一个服务器节点上。
其分布如图:

image.png

这是一致性hash算法的基本原理,接下来我们看一下,此算法是如何解决 我们上边 说的 缓存系统的扩展或者节点宕机导致的缓存失效的问题。比如:再加入一个redis节点:
image.png

如上图,当我们加入redis node5之后,影响的范围只有黄色标出的那部分,不会造成全局的变动。

除了上边的优点,其实还有一个优点:对于热点数据,如果发现node1访问量明显很大,负载高于其他节点,这就说明node1存储的数据是热点数据。这时候,为了减少node1的负载,我们可以在热点数据位置再加入一个node,用来分担热点数据的压力。
雪崩效应

接下来我们来看一下,当有节点宕机时会有什么问题。如下图:


image.png

如上图,当B节点宕机后,原本存储在B节点的k1,k2将会迁移到节点C上,这可能会导致很大的问题。如果B上存储的是热点数据,将数据迁移到C节点上,然后C需要承受B+C的数据,也承受不住,也挂了。。。。然后继续CD都挂了。这就造成了雪崩效应。
上面会造成雪崩效应的原因分析:
如果不存在热点数据的时候,每台机器的承受的压力是M/2(假设每台机器的最高负载能力为M),原本是不会有问题的,但是,这个时候A服务器由于有热点数据挂了,然后A的数据迁移至B,导致B所需要承受的压力变为M(还不考虑热点数据访问的压力),所以这个失败B是必挂的,然后C至少需要承受1.5M的压力。。。。然后大家一起挂。。。
所以我们通过上面可以看到,之所以会大家一起挂,原因在于如果一台机器挂了,那么它的压力全部被分配到一台机器上,导致雪崩。

怎么解决雪崩问题呢,这时候需要引入虚拟节点来进行解决。
虚拟节点

虚拟节点,我们可以针对每个实际的节点,虚拟出多个虚拟节点,用来映射到圈上的位置,进行存储对应的数据。如下图:


image.png

如上图:A节点对应A1,A2,BCD节点同理。这时候,如果A节点挂了,A节点的数据迁移情况是:A1数据会迁移到C2,A2数据迁移到D1。这就相当于A的数据被C和D分担了,这就避免了雪崩效应的发送,而且虚拟节点我们可以自定义设置,使其适用于我们的应用。

ngx_http_upstream_consistent_hash
该模块可以根据配置参数采取不同的方式将请求均匀映射到后端机器,比如:

consistent_hash $remote_addr:可以根据客户端ip映射
consistent_hash $request_uri: 根据客户端请求的uri映射
consistent_hash $args:根据客户端携带的参数进行映射

指令
语法:consistent_hash variable_name
默认值:none
上下文:upstream

配置upstream采用一致性hash作为负载均衡算法,并使用配置的变量名作为hash输入。

安装
# wget https://github.com/replay/ngx_http_consistent_hash/archive/master.zip
# unzip master.zip 
# ./configure  --add-module=./3thparty/ngx_http_consistent_hash-master
# make
# make install

# wget https://github.com/replay/ngx_http_consistent_hash/archive/master.zip
# unzip master.zip 
# ./configure  --add-module=./3thparty/ngx_http_consistent_hash-master
# make
# make install
例子
   upstream somestream {
      consistent_hash $request_uri;
      server 10.50.1.3:11211;
      server 10.50.1.4:11211;
      server 10.50.1.5:11211;
    }
 
...
 
server {
        listen       80;
        server_name  localhost;
 
        location / {
          default_type text/html;
          set $memcached_key $request_uri;
          memcached_pass somestream;
          error_page      500 404 405 = @fallback;
        }
 
        location @fallback {
          root /srv/www/whatever;
          fastcgi_intercept_errors on;
          error_page 404 = @404;
 
          set $script $uri;
          set $path_info "";
 
          include /usr/local/nginx/conf/fastcgi_params;
          fastcgi_param SCRIPT_FILENAME /srv/www/whatever/test.php;
          fastcgi_param SCRIPT_NAME $script;
          fastcgi_param REQUEST_URI $uri;
          fastcgi_pass   127.0.0.1:9000;
        }
    }

   upstream somestream {
      consistent_hash $request_uri;
      server 10.50.1.3:11211;
      server 10.50.1.4:11211;
      server 10.50.1.5:11211;
    }
 
server {
        listen       80;
        server_name  localhost;
 
        location / {
          default_type text/html;
          set $memcached_key $request_uri;
          memcached_pass somestream;
          error_page      500 404 405 = @fallback;
        }
 
        location @fallback {
          root /srv/www/whatever;
          fastcgi_intercept_errors on;
          error_page 404 = @404;
 
          set $script $uri;
          set $path_info "";
 
          include /usr/local/nginx/conf/fastcgi_params;
          fastcgi_param SCRIPT_FILENAME /srv/www/whatever/test.php;
          fastcgi_param SCRIPT_NAME $script;
          fastcgi_param REQUEST_URI $uri;
          fastcgi_pass   127.0.0.1:9000;
        }
    }

参考文档:
https://www.cnblogs.com/FengGeBlog/p/10615345.html
http://www.ttlsa.com/nginx/nginx-upstream-consistent-hash-module/

你可能感兴趣的:(nginx 负载均衡之一致性hash,普通hash)