负载均衡 LB(Load Balance)-- 算法(策略)

@[email protected]

上一篇介绍了负载均衡的内容和分类,这篇文章主要说明一下一些常用的负载均衡算法。

   在实际的应用过程中,往往不会在不管服务器是否满载或者宕机让客户端的请求平均的被分配给内部的各个服务器来处理。一般会让配置更高的机器接受更多的服务请求,一台处理服务请求较少的服务器能分配到更多的服务请求,出现故障的服务器将不再接受服务请求直至故障恢复等等。
   之所以要采用负载均衡的算法或者策略,就是为了让多个设备在一起共同更好的完成任务,避免或则消除网络负载分布不均、数据流量拥挤反应时间过长的瓶颈。

负载算法

  解决后端系统的承载能力,,一般经常使用的有两种方法,
  1)手动配置
  对于中小系统而言,手动配置是最方便有效的也是最稳定的方式。因为管理人员知道自己后端服务器的参数配置,部署的服务,了解其大概的性能和承载能力,所以在配置的时候,可以预先分配好最大承载压力。
  比如,某nginx的配置如下:
    upstream simplemain.com {
    server  192.168.1.100:8080 weight=30;
    server  192.168.1.101:8080 weight=70;
    }

   上述的配置的含义即有两台后端的服务器,一台的性能明显优于另外一台,更强的,我们就给他70%的压力;弱一点的,我们就给他30%的压力。这样,nginx就会把更多的压力分配给第二台。

   这种方式配置简单,而且很稳定,基本不会产生分配的抖动。不过,带来的问题就是分配很固定,不能动态调整。如果你的后端服务器有一段时间出现性能抖动(比如有其他服务扰动了机器的稳定运行,造成cpu利用率一段时间升高),前端调用者就很难根据实际的情况重新分配请求压力。所以,引入了第二种方法。

2)动态调整
   该方案能够根据机器目前的运行状态,通过对比历史平均值,如果发现当前状态好过历史平均值,就会增加请求压力;如果发现比历史平均状况要糟糕,就会动态的请求减少请求的数量。

   这种方案的好处在于可以动态的来平衡后面服务器的处理能力。不过,任何事物都有两面性。这种方案如果遇到极端情况,可能会造成系统雪崩!当某台机器出现短暂网络抖动的时候,他的响应就可能变慢,这个时候,前端服务就会将他的请求分配给其他的机器。如果分配的很多,就有可能造成某些机器响应也变慢。然后又将这些机器的请求分配给另外的……如此这般,运行着的机器终将被这些请求压死。

   更好的方式是将两者结合起来使用。通过预先静态配置一个承载负荷的范围,超过这个负荷就将其抛弃。同时动态的监控后端机器的响应情况,做出相应的动态请求调整。

均衡算法

均衡算法主要解决的问题是用何种方式将请求发送给后端服务器。

1)随机(random)算法
   依旧采用上面30-70的例子,算法的伪代码描述:
   bool res = abs(rand()) % 100 < 30

1、先产生一个伪随机数:rand()
2、将这个伪随机数的转化为非负数: abs(rand())
3、将这个数取模100,将值转化到[0,100)的半开半闭区间:abs(rand()) % 100
4、看这个数是否落入了前30个数的区间[0,30):abs(rand()) % 100 < 30
如果随机是均匀的话,他们落到[0,100)这个区间里一定是均匀的,所以只要在[0,30)这个区间里,就分给第一台机器,否则就分给第二台机器。

   随机算法是最常用的算法。从概率上讲,它能保证请求基本是分散的,从而达到我们想要的均衡效果;其次,它又是无状态的,不需要维持上一次的选择状态,也不需要均衡因子等。

2)轮训(round-robin)算法
   就像字面上的理解,轮训算法就像是挨个数数一样(123-123-123……)。
   上面的例子的可表述为:

第一台机器叫做A,第二台叫做B:
1、先给两台机器做个排序的数组:array = [ABBABBABBB]
2、用一个计数指针来标明现在数组的位置:idx = 3
3、当一个请求来的时候,我们就把指针对应的机器选取出来,并且指针加一,挪到下一个位置。
这样,十个请求,我们就可以保证有3个一定是A,7个一定是B。
因为要维护idx指针,所以轮询算法是有状态的。

3)一致哈希(consistent-hash)算法
一致Hash要解决的是两个问题:
   1、散列的不变性:就是同一个请求(比如:同一个用户id)尽量的落入到一台机器,不要因为时间等其他原因,落入到不同的机器上了;
   2、异常以后的分散性:当某些机器坏掉(或者增加机器),原来落到同一台机器的请求(比如:用户id为1,101,201),尽量分散到其他机器,不要都落入其他某一台机器。这样对于系统的冲击和影响最小。

  一致Hash算法用的最多的场景,就是分配cache服务。将某一个用户的数据缓存在固定的某台服务器上,那么我们基本上就不用多台机器都缓存同样的数据,这样对我们提高缓存利用率有极大的帮助。

  不过硬币都是有两面的,一致Hash也不例外。当某台机器出问题以后,这台机器上的cache失效,原先压倒这台机器上的请求,就会压到其他机器上。由于其他机器原先没有这些请求的缓存,就有可能直接将请求压到数据库上,造成数据库瞬间压力增大。如果压力很大的话,有可能直接把数据库压垮。

  所以,在考虑用一致Hash算法的时候,一定要估计一下如果有机器宕掉后,后端系统是否能承受对应的压力。如果不能,则建议浪费一点内存利用率,使用随机算法。


4)主备(master-slave)算法
  算法核心的思想是将请求尽量的放到某个固定机器的服务上,而其他机器的服务则用来做备份,如果出现问题就切换到另外的某台机器的服务上。

你可能感兴趣的:(负载均衡)