LVS集群之十种调度算法及负载均衡——理论

来源:互联网 发布:怎么读取poi数据 编辑:程序博客网 时间:2024/05/17 23:22
 LVS集群之十种调度算法及负载均衡——理论
2013-05-13 18:36:47
标签:LVS的十种调度算法 负载均衡 LB HP HA
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://lzysg172.blog.51cto.com/6624306/1199412

一、LVS概念

LVS(Linux Virtual Server):Linux 虚拟服务器

      LVS是个负载均衡设备,它不提供任何服务,用户请求到这里的时候,它是将客户需求转发至后端真正提供服务的服务,所以说后端的服务称作real server。LVS分为两段,前一段称为ipvsadm(管理集群服务的命令行工具),后面一段叫做ipvs(内核模块)【提示:LVSiptables不能同时使用】

二、LVS类型

      LB(Load Balancing):负载均衡集群

特性:为了增加能力能力

      HA(High Availability):高可用集群

特性:提供服务的可用性(一年在线时间达到99.999%才行)

计算方法:在线时间/(在线时间/故障处理时间)

      HP([HPC]High Performance):高性能集群

特性:提供服务的性能

三、LVS组成结构(负载均衡实现方案)

基于DNS域名轮流解析的方法

基于客户端调度访问的方法

基于应用层系统负载的调度方法

基于IP地址的调度方法

其中基于IP的负载调度算法中,IP负载均衡技术是执行效率最高的

四、LVS十种调度算法

1、静态调度:

      ①rr(Round Robin):轮询调度,轮叫调度

      轮询调度算法的原理是每一次把来自用户的请求轮流分配给内部中的服务器,从1开始,直到N(内部服务器个数),然后重新开始循环。算法的优点是其简洁性,它无需记录当前所有连接的状态,所以它是一种无状态调度。【提示:这里是不考虑每台服务器的处理能力】

     ②wrr:weight,加权(以权重之间的比例实现在各主机之间进行调度)

     由于每台服务器的配置、安装的业务应用等不同,其处理能力会不一样。所以,我们根据服务器的不同处理能力,给每个服务器分配不同的权值,使其能够接受相应权值数的服务请求。

③sh:source hashing,源地址散列。主要实现会话绑定,能够将此前建立的session信息保留了

源地址散列调度算法正好与目标地址散列调度算法相反,它根据请求的源IP地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的并且没有超负荷,将请求发送到该服务器,否则返回空。它采用的散列函数与目标地址散列调度算法的相同。它的算法流程与目标地址散列调度算法的基本相似,除了将请求的目标IP地址换成请求的源IP地址,所以这里不一个一个叙述。

④Dh:Destination hashing:目标地址散列。把同一个IP地址的请求,发送给同一个server。

目标地址散列调度算法也是针对目标IP地址的负载均衡,它是一种静态映射算法,通过一个散列(Hash)函数将一个目标IP地址映射到一台服务器。目标地址散列调度算法先根据请求的目标IP地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。

2、动态调度

①lc(Least-Connection):最少连接

最少连接调度算法是把新的连接请求分配到当前连接数最小的服务器,最小连接调度是一种动态调度短算法,它通过服务器当前所活跃的连接数来估计服务器的负载均衡,调度器需要记录各个服务器已建立连接的数目,当一个请求被调度到某台服务器,其连接数加1,当连接中止或超时,其连接数减一,在系统实现时,我们也引入当服务器的权值为0时,表示该服务器不可用而不被调度。

简单算法:active*256+inactive(谁的小,挑谁)

②wlc(Weighted Least-Connection Scheduling):加权最少连接。

加权最小连接调度算法是最小连接调度的超集,各个服务器用相应的权值表示其处理性能。服务器的缺省权值为1,系统管理员可以动态地设置服务器的权限,加权最小连接调度在调度新连接时尽可能使服务器的已建立连接数和其权值成比例。

简单算法:(active*256+inactive)/weight【(活动的连接数+1)/除以权重】(谁的小,挑谁)

③sed(Shortest Expected Delay):最短期望延迟

基于wlc算法

简单算法:(active+1)*256/weight 【(活动的连接数+1)*256/除以权重】

④nq(never queue):永不排队(改进的sed)

无需队列,如果有台realserver的连接数=0就直接分配过去,不需要在进行sed运算。

⑤LBLC(Locality-Based Least Connection):基于局部性的最少连接

基于局部性的最少连接算法是针对请求报文的目标IP地址的负载均衡调度,不签主要用于Cache集群系统,因为Cache集群中客户请求报文的布标IP地址是变化的,这里假设任何后端服务器都可以处理任何请求,算法的设计目标在服务器的负载基本平衡的情况下,将相同的目标IP地址的请求调度到同一个台服务器,来提高个太服务器的访问局部性和主存Cache命中率,从而调整整个集群系统的处理能力。

基于局部性的最少连接调度算法根据请求的目标IP地址找出该目标IP地址最近使用的RealServer,若该Real Server是可用的且没有超载,将请求发送到该服务器;若服务器不存在,或者该服务器超载且有服务器处于一半的工作负载,则用“最少链接”的原则选出一个可用的服务器,将请求发送到该服务器。

⑥LBLCRLocality-Based Least Connections withReplication):带复制的基于局部性最少链接

      带复制的基于局部性最少链接调度算法也是针对目标IP地址的负载均衡,该算法根据请求的目标IP地址找出该目标IP地址对应的服务器组,按“最小连接”原则从服务器组中选出一台服务器,若服务器没有超载,将请求发送到该服务器;若服务器超载,则按“最小连接”原则从这个集群中选出一台服务器,将该服务器加入到服务器组中,将请求发送到该服务器。同时,当该服务器组有一段时间没有被修改,将最忙的服务器从服务器组中删除,以降低复制的程度。

五、IPVS实现负载均衡的方法

NAT:地址转换(类似于DNAT

             1、集群点跟director必须工作在同一个IP的网络中

             2、RIP通常是私有地址,仅用于各集群节点间的的通信

             3、director位于client和real server之间,并负责处理进出的所有通道。

             4、realserver必须将网关执行DIP

             5、director支持端口映射

             6、realserver可以使用任何类型的操作系统(os

             7、较大规模应用场景中,director易成为系统瓶颈

DR:直接路由(及用于作为源地址)

             1、各集群节点跟director必须在同一个物理网络中;

             2、RIP可以使用公网地址,实现便携的远程管理和监控;

             3、director仅负责处理入站请求,形影报文则有realserver直接发往客户端

             4、realserver不能将网关指向DIP,而是直接指向前端网关;

             5、director不支持端口映射

             6、大多数操作系统能够用在realserver

             7、director能够处理更多的realserver

   TUN:隧道

             1、集群节点可以跨越Internet

             2、RIP必须是公网地址

             3、director仅负责处理入站请求,形影报文则有realserver直接发往客户端

             4、realserver网关不能指向director

             5、只有咫尺隧道功能的OS才能用于realserver

             6、不支持端口映射

六、ipvsadm常用命令

ipvsadm:

      1、管理集群服务

           添加:-A -t|u|f service-address [-sscheduler]

                      -t:tcp协议的集群服务

                      -u:udp协议的集群

                      -f:FWM:防火墙标记

           修改:-E

           删除:-D

                      -D -t|u|f service-address    

                   例如:# ipvsadm -A -t 172.16.100.1:80 -s rr

      2管理集群服务中的RS

           添加:-a -t|u|f service-address -rserver-address [-g|i|m] [-w weight]

                      -t|u|f service-address:事先定义好的某集群服务

                      -r server-address:某RS的地址,在NAT模型中,可以使用IP:PORT事先端口映射

                      [-g|i|m]:LVS类型

                           -g:DR

                           -I:TUN

                           -m:NAT

                      [-w weight]:定义服务器权重

       3、修改:-e

       4、删除:-d -t|u|f service-address -r server-address

                   例如:#ipvsadm -a -t 172.16.100.1:80 -r192.168.10.8 -m

                   例如:#ipvsadm-a -t 172.16.100.1:80 -r 192.168.10.9 -m

       5查看

                    -L|l[options]

                           -n:数字格式显示主机地址和端口号

                           --stats:统计信息

                           --rate:速率

                           --timeout:显示tcp、tcpfin和udp会话的超时时间值

                           --daemon

                           --sort:跟协议、地址、端口进行排序,默认为升序

                           -c:显示当前ipvs连接状况

       6、删除所有集群服务:

                    -C:清空ipvs规则

       7、保存规则

                    -S:(用输出重定向进行保存)

                    格式:#ipvsadm -s >/path/to/somefile

       8、载入此前的规则:

                    -R

                     格式:#ipvsadm -R </path/to/somefile

动态反馈负载均衡算法

动态反馈负载均衡算法考虑服务器的实时负载和响应情况,不断调整服务器间处理请求的比例,来避免有些服务器超载时依然收到大量请求,从而提高整个系统的吞吐率。图4.1显示了该算法的工作环境,在负载调度器上运行Monitor Daemon进程,Monitor Daemon来监视和收集各个服务器的负载信息。Monitor Daemon可根据多个负载信息算出一个综合负载值。Monitor Daemon将各个服务器的综合负载值和当前权值算出一组新的权值,若新权值和当前权值的差值大于设定的阀值,Monitor Daemon将该服务器的权值设置到内核中的IPVS调度中,而在内核中连接调度一般采用加权轮叫调度算法或者加权最小连接调度算法。



图4.1:动态反馈负载均衡算法的工作环境

连接调度

当客户通过TCP连接访问网络访问时,服务所需的时间和所要消耗的计算资源是千差万别的,它依赖于很多因素。例如,它依赖于请求的服务类型、当前网络带宽的情况、以及当前服务器资源利用的情况。一些负载比较重的请求需要进行计算密集的查询、数据库访问、很长响应数据流;而负载比较轻的请求往往只需要读一个HTML页面或者进行很简单的计算。

请求处理时间的千差万别可能会导致服务器利用的倾斜(Skew),即服务器间的负载不平衡。例如,有一个WEB页面有A、B、C和D文件,其中D是大图像文件,浏览器需要建立四个连接来取这些文件。当多个用户通过浏览器同时访问该页面时,最极端的情况是所有D文件的请求被发到同一台服务器。所以说,有可能存在这样情况,有些服务器已经超负荷运行,而其他服务器基本是闲置着。同时,有些服务器已经忙不过来,有很长的请求队列,还不断地收到新的请求。反过来说,这会导致客户长时间的等待,觉得系统的服务质量差。

简单连接调度

简单连接调度可能会使得服务器倾斜的发生。在上面的例子中,若采用轮叫调度算法,且集群中正好有四台服务器,必有一台服务器总是收到D文件的请求。这种调度策略会导致整个系统资源的低利用率,因为有些资源被用尽导致客户的长时间等待,而其他资源空闲着。

实际TCP/IP流量的特征

文献说明网络流量是呈波浪型发生的,在一段较长时间的小流量后,会有一段大流量的访问,然后是小流量,这样跟波浪一样周期性地发生。文献揭示在WAN和LAN上网络流量存在自相似的特征,在WEB访问流也存在自相似性。这就需要一个动态反馈机制,利用服务器组的状态来应对访问流的自相似性。

动态反馈负载均衡机制

TCP/IP流量的特征通俗地说是有许多短事务和一些长事务组成,而长事务的工作量在整个工作量占有较高的比例。所以,我们要设计一种负载均衡算法,来避免长事务的请求总被分配到一些机器上,而是尽可能将带有毛刺(Burst)的分布分割成相对较均匀的分布。

我们提出基于动态反馈负载均衡机制,来控制新连接的分配,从而控制各个服务器的负载。例如,在IPVS调度器的内核中使用加权轮叫调度(Weighted Round-Robin Scheduling)算法来调度新的请求连接;在负载调度器的用户空间中运行Monitor Daemon。Monitor Daemon定时地监视和收集各个服务器的负载信息,根据多个负载信息算出一个综合负载值。Monitor Daemon将各个服务器的综合负载值和当前权值算出一组新的权值。当综合负载值表示服务器比较忙时,新算出的权值会比其当前权值要小,这样新分配到该服务器的请求数就会少一些。当综合负载值表示服务器处于低利用率时,新算出的权值会比其当前权值要大,来增加新分配到该服务器的请求数。若新权值和当前权值的差值大于设定的阀值,Monitor Daemon将该服务器的权值设置到内核中的IPVS调度中。过了一定的时间间隔(如2秒钟),Monitor Daemon再查询各个服务器的情况,并相应调整服务器的权值;这样周期性地进行。可以说,这是一个负反馈机制,使得服务器保持较好的利用率。

在加权轮叫调度算法中,当服务器的权值为零,已建立的连接会继续得到该服务器的服务,而新的连接不会分配到该服务器。系统管理员可以将一台服务器的权值设置为零,使得该服务器安静下来,当已有的连接都结束后,他可以将该服务器切出,对其进行维护。维护工作对系统都是不可少的,比如硬件升级和软件更新等,零权值使得服务器安静的功能很主要。所以,在动态反馈负载均衡机制中我们要保证该功能,当服务器的权值为零时,我们不对服务器的权值进行调整。

综合负载

在计算综合负载时,我们主要使用两大类负载信息:输入指标和服务器指标。输入指标是在调度器上收集到的,而服务器指标是在服务器上的各种负载信息。我们用综合负载来反映服务器当前的比较确切负载情况,对于不同的应用,会有不同的负载情况,这里我们引入各个负载信息的系数,来表示各个负载信息在综合负载中轻重。系统管理员根据不同应用的需求,调整各个负载信息的系数。另外,系统管理员设置收集负载信息的时间间隔。

输入指标主要是在单位时间内服务器收到新连接数与平均连接数的比例,它是在调度器上收集到的,所以这个指标是对服务器负载情况的一个估计值。在调度器上有各个服务器收到连接数的计数器,对于服务器Si,可以得到分别在时间T1和T2时的计数器值Ci1和Ci2,计算出在时间间隔T2-T1内服务器 Si收到新连接数Ni = Ci2 - Ci1。这样,得到一组服务器在时间间隔T2-T1内服务器Si收到新连接数{Ni},服务器Si的输入指标INPUTi为其新连接数与n台服务器收到平均连接数的比值,其公式为

服务器指标主要记录服务器各种负载信息,如服务器当前CPU负载LOADi、服务器当前磁盘使用情况Di、当前内存利用情况Mi和当前进程数目 Pi。有两种方法可以获得这些信息;一是在所有的服务器上运行着SNMP(Simple Network Management Protocol)服务进程,而在调度器上的Monitor Daemon通过SNMP向各个服务器查询获得这些信息;二是在服务器上实现和运行收集信息的Agent,由Agent定时地向Monitor Daemon报告负载信息。若服务器在设定的时间间隔内没有响应,Monitor Daemon认为服务器是不可达的,将服务器在调度器中的权值设置为零,不会有新的连接再被分配到该服务器;若在下一次服务器有响应,再对服务器的权值进行调整。再对这些数据进行处理,使其落在[0, ∞)的区间内,1表示负载正好,大于1表示服务器超载,小于1表示服务器处于低负载状态。获得调整后的数据有DISKi、MEMORYi和 PROCESSi。

另一个重要的服务器指标是服务器所提供服务的响应时间,它能比较好地反映服务器上请求等待队列的长度和请求的处理时间。调度器上的Monitor Daemon作为客户访问服务器所提供的服务,测得其响应时间。例如,测试从WEB服务器取一个HTML页面的响应延时,Monitor Daemon只要发送一个“GET /”请求到每个服务器,然后记录响应时间。若服务器在设定的时间间隔内没有响应,Monitor Daemon认为服务器是不可达的,将服务器在调度器中的权值设置为零。同样,我们对响应时间进行如上调整,得到RESPONSEi。

这里,我们引入一组可以动态调整的系数Ri来表示各个负载参数的重要程度,其中ΣRi = 1。综合负载可以通过以下公式计算出:

例如,在WEB服务器集群中,我们采用以下系数{0.1, 0.3, 0.1, 0.1, 0.1, 0.3},认为服务器的CPU负载和请求响应时间较其他参数重要一些。若当前的系数Ri不能很好地反映应用的负载,系统管理员可以对系数不断地修正,直到找到贴近当前应用的一组系数。

另外,关于查询时间间隔的设置,虽然很短的间隔可以更确切地反映各个服务器的负载,但是很频繁地查询(如1秒钟几次)会给调度器和服务器带来一定的负载,如频繁执行的Monitor Daemon在调度器会有一定的开销,同样频繁地查询服务器指标会服务器带来一定的开销。所以,这里要有个折衷(Tradeoff),我们一般建议将时间间隔设置在5到20秒之间。

权值计算

当服务器投入集群系统中使用时,系统管理员对服务器都设定一个初始权值DEFAULT_WEIGHTi,在内核的IPVS调度中也先使用这个权值。然后,随着服务器负载的变化,对权值进行调整。为了避免权值变成一个很大的值,我们对权值的范围作一个限制[DEFAULT_WEIGHTi, SCALE*DEFAULT_WEIGHTi],SCALE是可以调整的,它的缺省值为10。

Monitor Daemon周期性地运行,若DEFAULT_WEIGHTi不为零,则查询该服务器的各负载参数,并计算出综合负载值AGGREGATE_LOADi。我们引入以下权值计算公式,根据服务器的综合负载值调整其权值。

在公式中,0.95是我们想要达到的系统利用率,A是一个可调整的系数(缺省值为5)。当综合负载值为0.95时,服务器权值不变;当综合负载值大于0.95时,权值变小;当综合负载值小于0.95时,权值变大。若新权值大于SCALE*DEFAULT_WEIGHTi,我们将新权值设为 SCALE*DEFAULT_WEIGHTi。若新权值与当前权值的差异超过设定的阀值,则将新权值设置到内核中的IPVS调度参数中,否则避免打断 IPVS调度的开销。我们可以看出这是一个负反馈公式,会使得权值调整到一个稳定点,如系统达到理想利用率时,权值是不变的。

在实际使用中,若发现所有服务器的权值都小于他们的DEFAULT_WEIGHT,则说明整个服务器集群处于超载状态,这时需要加入新的服务器结点到集群中来处理部分负载;反之,若所有服务器的权值都接近于SCALE*DEFAULT_WEIGHT,则说明当前系统的负载都比较轻。

一个实现例子

我们在RedHat集群管理工具Piranha[6]中实现了一个简单的动态反馈负载均衡算法。在综合负载上,它只考虑服务器的CPU负载(Load Average),使用以下公式进行权值调整:

服务器权值调整区间为[DEFAULT_WEIGHTi, 10*DEFAULT_WEIGHTi],A为DEFAULT_WEIGHTi /2,而权值调整的阀值为DEFAULT_WEIGHTi /4。1是所想要达到的系统利用率。Piranha每隔20秒查询各台服务器的CPU负载,进行权值计算和调整。



 负载均衡算法小结 2011-05-05 19:15:37

分类: C/C++

互联网分布式系统中,很多服务是数据存储相关的,海量访问量下,直接访问存储介质是抗不住的,需要使用cache,cache集群的负载均衡算法就成为一个重要的话题,这里对现有的负载均衡算法进行一些总结。
BTW:虽然是Cache负载均衡算法小结,其实可以说是负载均衡算法小结,只是针对Cache应用场景罢了。

负载均衡算法主要有:
Static算法
Random算法
Round robin算法
Hash算法
CARP算法
Consistent hash算法

Static算法
负载均衡的石器时代,为一个服务指定多个IP:PORT,备份模式,其总是返回服务器组的第一个服务器(只要第一个服务器可用),当第一个服务器没有用的时候,才会返回后续可用的服务器。
这种情况下,每台机器都包括全量的数据,查询通常会落到第一台机器上,第一台机器上Cache命中率高,但是当失败的时候,落到第二胎机器上,那就杯具了,Cache命中率那个低啊!!!

Random算法
地球人都知道的算法,对于无状态服务比较适用,随便选取一台机器就可以。
idx=rand()%M
在实际使用中,跟Static算法一样,都是模块维护全量数据,这个还好每台机器的cache命中率理论上应该差不多,但是都不高,为啥呢?因为同样一个请求一会落到机器A,一会落到机器B上。败家子啊,浪费内存啊,内存有限,Cache会被淘汰,频繁淘汰,当然使得命中率低下啊。

Round robin算法
典型的平均主义,吃大锅饭的,皇帝轮流做啊,顺序依次选取服务器。
idx=(idx+1)%M
同样的模块维护全量数据,跟Random一样杯具,基本上一样的原因。相同的请求会被落到不同的机器上,导致Cache命中率低。

Hash算法
又叫取余算法,将query key做hash之后,按照机器数量取余,选取中一个机器进行连接服务。
idx=hash(query_key)%M
余数计算的方法简单,数据的分散性也相当优秀,但也有其缺点。那就是当添加或移除服务器时,缓存重组的代价相当巨大。添加服务器后,余数就会产生巨变,这样就无法获取与保存时相同的服务器,从而影响缓存的命中率。

CARP算法
CARP准确的说不是一个算法,而是一个协议,Cache Array Routing Protocol,Cache群组路由协议。
计算全部服务器的idx_key=hash(query_key+server_idx),其中计算得到idx_key最大的server_idx就是需要的idx。
假设开始3台后端服务器,请求用标志串 req = "abcd" 来标志,服务器用 S1, S2, S3来标志, 那么,通过对 req + Sx 合并起来计算签名就可以对每个服务器得到一个数值:
(req = "abcd" + S1) = K1
(req = "abcd" + S2) = K2
(req = "abcd" + S3) = K3
计算的方法可以使用crc,也可以使用MD5,目的的得到一个*散列*的数字,这样在K1,K2,K3中 必定有一个最大的数值,假设是K2,那么可以将请求req扔给S2,这样,以后对相同的请求, 相同的服务器组,计算出来的结果必定是K2最大,从而达到HASH分布的效果。
巧妙的地方在于,新增或者删除一台服务器的时候,不会引起已有服务器的cache大规模失效, 假设新增一台服务器S4,那么对S1,S2,S3计算的K值都完全相同,那么对S4可以计算得到一个新值K4,如果计算K的算法足够散列,那么原先计算到S1,S2,S3的请求,理论上都会有1/4的请求新计算得到的K4比原先的K大, 那么这1/4的请求会转移到S4,从而新增的S4服务器会负担1/4的请求,原先的S1,S2,S3也只会负担原先的3/4。

Consistent hash算法
一致性hash算法是:首先求出服务器(节点)的哈希值,并将其配置到0~2^32的圆(continuum)上。然后用同样的方法求出存储数据的键的哈希值,并映射到圆上。然后从数据映射到的位置开始顺时针查找,将数据保存到找到的第一个服务器上。如果超过2^32仍然找不到服务器,就会保存到第一台服务器上。
idx=FirstMaxServerIdx(hash(query_key))


添加节点的时候:


consistent hash算法背后最基础的思想就是:对object和cache machine使用相同的hash函数【DHT算法的核心啊,P2P的理论基石啊,资源和地址节点在统一地址空间进行编址】。Consistent Hash适用于每个节点只保存部分数据,而不是像前面几种算法,每个节点保存全量数据。这样做的好处是能够把cache机器映射到一段interval上,而这段interval就会包含一定数目的对象的hash值。如果某台cache机器被移除了,那么它映射到的interval被和它相邻的一个cache机器托管,其他所有的cache机器都不用变。

一致性哈希算法最大程度的避免了key在服务节点列表上的重新分布,其他附带的改进就是有的一致性 哈希算法还增加了虚拟服务节点的方法,也就是一个服务节点在环上有多个映射点,这样就能抑制分布不均匀,最大限度地减小服务节点增减时的缓存重新分布。


参考:
http://icp.ircache.net/carp.txt
http://hi.baidu.com/fdwm_lx/blog/item/f670e73582c8411d90ef3950.html
http://blog.csdn.net/sparkliang/archive/2010/02/02/5279393.aspx

负载均衡的基本算法

负载均衡的基本算法,主要有以下几种(参考F5产品):

  • 随机:负载均衡方法随机的把负载分配到各个可用的服务器上,通过随机数生成算法选取一个服务器,然后把连接发送给它。虽然许多均衡产品都支持该算法,但是它的有效性一直受到质疑,除非把服务器的可运行时间看的很重。
  • 轮询:轮询算法按顺序把每个新的连接请求分配给下一个服务器,最终把所有请求平分给所有的服务器。轮询算法在大多数情况下都工作的不错,但是如果负载均衡的设备在处理速度、连接速度和内存等方面不是完全均等,那么效果会更好。
  • 加权轮询:该算法中,每个机器接受的连接数量是按权重比例分配的。这是对普通轮询算法的改进,比如你可以设定:第三台机器的处理能力是第一台机器的两倍,那么负载均衡器会把两倍的连接数量分配给第3台机器。
  • 动态轮询:类似于加权轮询,但是,权重值基于对各个服务器的持续监控,并且不断更新。这是一个动态负载均衡算法,基于服务器的实时性能分析分配连接,比如每个节点的当前连接数或者节点的最快响应时间等。
  • 最快算法:最快算法基于所有服务器中的最快响应时间分配连接。该算法在服务器跨不同网络的环境中特别有用。
  • 最少连接:系统把新连接分配给当前连接数目最少的服务器。该算法在各个服务器运算能力基本相似的环境中非常有效。
  • 观察算法:该算法同时利用最小连接算法和最快算法来实施负载均衡。服务器根据当前的连接数和响应时间得到一个分数,分数较高代表性能较好,会得到更多的连接。
  • 预判算法:该算法使用观察算法来计算分数,但是预判算法会分析分数的变化趋势来判断某台服务器的性能正在改善还是降低。具有改善趋势的服务器会得到更多的连接。该算法适用于大多数环境。

性能调优社区dynatrace在其博客中分享了客户案例,电商网站在假日客流峰值期间数次崩溃,经过SQL优化和调整负载均衡算法解决了相关问题.首先要分析执行最慢的数据库语句,并做性能优化,比如增加索引等。同时也优化了连接池大小来满足高峰时刻的需求。然后,企业把负载均衡器的算法从Round-Robin改为了Least-Busy。

相关文章:

电商网站的宕机案例分析

ASP.NET Session State Partitioning

ASP.NET Session State Partitioning using State Server Load Balancing

解析nginx负载均衡

Round Robin Scheduling

 

using System;using System.Collections.Generic;using System.Linq;using System.Runtime.CompilerServices;using System.Text;namespace LoadBalancer{    public class LoadBalance    {        /// <summary>        /// 锁对象        /// </summary>        private static readonly object locker = new object();        /// <summary>        /// 服务器权重列表        /// </summary>        private static List<int> weightList = new List<int>();        /// <summary>        /// 当前索引        /// </summary>        private static int currentIndex;        /// <summary>        /// 当前权重        /// </summary>        private static int currentWeight;        private static int maxWeight;        /// <summary>        /// 最大公约数        /// </summary>        private static int gcd;        static LoadBalance()        {            currentIndex = -1;            currentWeight = 0;            //获取服务器权重列表,从配置文件            weightList = GetWeightList();            maxWeight = GetMaxWeight(weightList);            gcd = GetMaxGCD(weightList);        }        private static List<int> GetWeightList()        {            List<int> list = new List<int>();            list.Add(3);            list.Add(1);            list.Add(1);            list.Add(4);            list.Add(1);            list.Add(7);            return list;        }        [MethodImpl(MethodImplOptions.Synchronized)]        public static int Start()        {            lock (locker)            {                int? iWeight = RoundRobin();                if (iWeight != null)                {                    return (int)iWeight;                }                return weightList[0];            }        }        /// <summary>        /// 获取最大公约数        /// </summary>        /// <param name="list">要查找的int集合</param>        /// <returns>返回集合中所有数的最大公约数</returns>        private static int GetMaxGCD(List<int> list)        {            list.Sort(new WeightCompare());            int iMinWeight = weightList[0];            int gcd = 1;            for (int i = 1; i < iMinWeight; i++)            {                bool isFound = true;                foreach (int iWeight in list)                {                    if (iWeight % i != 0)                    {                        isFound = false;                        break;                    }                }                if (isFound) gcd = i;            }            return gcd;        }        /// <summary>        /// 获取服务器权重集合中的最大权重        /// </summary>        /// <param name="list"></param>        /// <returns></returns>        private static int GetMaxWeight(List<int> list)        {            int iMaxWeight = 0;            foreach (int i in list)            {                if (iMaxWeight < i) iMaxWeight = i;            }            return iMaxWeight;        }        private static int? RoundRobin()        {            while (true)            {                currentIndex = (currentIndex + 1) % weightList.Count;                if (0 == currentIndex)                {                    currentWeight = currentWeight - gcd;                    if (0 >= currentWeight)                    {                        currentWeight = maxWeight;                        if (currentWeight == 0) return null;                    }                }                if (weightList[currentIndex] >= currentWeight)                {                    return weightList[currentIndex];                }            }        }    }    public class WeightCompare : IComparer<int>    {        public int Compare(int x, int y)        {            return x - y;        }    }}


淘宝:OceanBase分布式系统负载均衡案例分享

发表于2013-02-28 22:1128942次阅读| 来源支付宝112 条评论| 作者孙志东

负载均衡分布式存储集群算法存储淘宝OceanBase
摘要:Heroku的问题让我们意识到,在负载均衡测试时发现问题并妥善解决的成功经验有没有?于是,挖掘出“淘宝在双十一压测OB时发现存在严重的随机访问导致负载不均问题,并通过加权算法妥善解决”的成功案例,也就是本文。

编者按:在CSDN云计算频道日前所做的文章《响应高达6秒 用户揭露Heroku私自修改路由造成高支出》中,网友们认为这是“因随机调度+Rails的单线程处理导致延迟增加的负载均衡失败的案例”。但在负载均衡测试时就能发现问题并妥善解决的成功经验有没有?在随后的微博中,支付宝的@Leverly评论:“去年双11前的压测OB就发现了存在严重的随机访问导致负载不均问题,还好通过加权算法很好的解决了。” 引发了我们的关注,于是有了本文。重点是淘宝在“双十一”背后,OceanBase分布式系统负载均衡的经验分享。

以下为正文:

云计算所具备的低成本、高性能、高可用性、高可扩展性等特点与互联网应用日益面临的挑战不谋而合,成为近年来互联网领域的热门话题。作为一名技术人员不难理解在云计算的底层架构中,分布式存储是不可或缺的重要组成部分。国外知名的互联网公司如Google、Amazon、Facebook、Microsoft、Yahoo等都推出了各自的分布式存储系统,在国内OceanBase是淘宝自主研发的一个支持海量数据的高性能分布式数据库系统,实现了数千亿条记录、数百TB数据上的跨行跨表事务[1]。

在分布式系统中存在着著名的“短板理论”[2],一个集群如果出现了负载不均衡问题,那么负载最大的机器往往将成为影响系统整体表现的瓶颈和短板。为了避免这种情况的发生,需要动态负载均衡机制,以达到实时的最大化资源利用率,从而提升系统整体的吞吐

本文将结合OceanBase的实际应用和大家分享一个去年淘宝双十一前期的准备工作中遇到负载均衡相关案例,抛砖引玉,期望对大家的工作有所启发。

OceanBase架构介绍

OceanBase是一个具有自治功能的分布式存储系统,由中心节点RootServer、静态数据节点ChunkServer、动态数据节点UpdateServer以及数据合并节点MergeServer四个Server构成[1],如图1所示。


图1 OceanBase 架构图

  • Tablet:分片数据,最基本的存储单元,一般会存储多份,一个Table由多个tablet构成;
  • RootServer:负责集群机器的管理、Tablet定位、数据负载均衡、Schema等元数据管理等。
  • UpdateServer:负责存储动态更新数据,存储介质为内存和SSD,对外提供写服务;
  • ChunkServer:负责存储静态Tablet数据,存储介质为普通磁盘或者SSD。
  • MergeServer:负责对查询中涉及多个Tablet数据进行合并,对外提供读服务;

在一个集群中,Tablet的多个副本分别存储在不同的ChunkServer,每个ChunkServer负责一部分Tablet分片数据,MergeServer和ChunkServer一般会一起部署。

双十一前期准备

对于淘宝的大部分应用而言,“双十一”就是一年一度的一次线上压测。伴随流量不断刷新着历史新高,对每个系统的可扩展性提出了很大的挑战。为了迎战双十一各产品线对有可能成为瓶颈部分的流量进行预估和扩容成为刻不容缓的任务。在本文要分享的案例中,应用方根据历史数据预估读请求的访问峰值为7w QPS,约为平时的5-6倍,合计每天支持56亿次的读请求。当时OceanBase集群部署规模是36台服务器,存储总数据量为200亿行记录,每天支持24亿次的读请求。

当前集群的读取性能远不能满足需求,我们首先进行了一次扩容,上线了10台Chunkserver/Mergeserver服务器。由于OceanBase本身具有比较强的可扩展性,为集群加机器是一件非常简单的操作。中心节点Rootserver在新机器注册上线后,会启动Rebalance功能以Tablet为单位对静态数据进行数据迁移,见下图的示意,最终达到所有ChunkServer上数据分片的均衡分布。 

表 1. 某Table的Tablet列表


图2.1 Tablet在三台ChunkServer上的分布


图2.2加入一台机器Tablet迁移后的分布

扩容完成后引入线上流量回放机制进行压力测试,以验证当前集群的性能是否可以满足应用的双十一需求。我们使用了10台服务器共2000-4000个线程并发回放线上读流量对集群进行压测,很快发现集群整体的QPS在达到4万左右后,压测客户端出现大量超时现象,平均响应延迟已经超过阈值100ms,即使不断调整压力,系统的整体QPS也没有任何增大。此时观察整个集群机器的负载状态发现只有极个别服务器的负载超高,是其他机器的4倍左右,其他机器基本处于空闲状态,CPU、网络、磁盘IO都凸现了严重的不均衡问题

负载不均衡导致了整体的吞吐取决于负载最高的那台Server,这正是前文提到的典型 “短板理论”问题。

负载不均问题跟踪

客户端连接到OceanBase之后一次读请求的读流程如下图所示:


图3 客户端到OceanBase的读流程图

  1. Client 从RootServer获取到MergeServer 列表;
  2. Client将请求发送到某一台MergeServer;
  3. MergeServer从RootServer获取请求对应的ChunkServer位置信息;
  4. MergeServer将请求按照Tablet拆分成多个子请求发送到对应的ChunkServer;
  5. ChunkServer向UpdateServer请求最新的动态数据,与静态数据进行合并;
  6. MergeServer合并所有子请求的数据,返回给Client;

OceanBase的读请求流程看起来如此复杂,实际上第1步和第3步中Client与RootServer以及MergeServer与RootServer的两次交互会利用缓存机制来避免,即提高了效率,同时也极大降低了RootServer的负载。

分析以上的流程可知,在第2步客户端选择MergeServer时如果调度不均衡会导致某台MergeServer机器过载;在第4步MergeServer把子请求发送到数据所在的ChunkServer时,由于每个tablet会有多个副本,选择副本的策略如果不均衡也会造成ChunkServer机器过载。由于集群部署会在同一台机器会同时启动ChunkServer和MergeServer,无法简单区分过载的模块。通过查看OceanBase内部各模块的提供的监控信息比如QPS、Cache命中率、磁盘IO数量等,发现负载不均问题是由第二个调度问题引发,即MergeServer对ChunkServer的访问出现了不均衡导致了部分ChunkServer的过载。

ChunkServer是存储静态Tablet分片数据的节点,分析其负载不均的原因包含如下可能:

  1. 数据不均衡: ChunkServer上数据大小的分布是不均衡的,比如某些节点因为存储Tablet分片数据量多少的差异性而造成的不均衡;
  2. 流量不均衡:数据即使是基本均衡的情况下,仍然会因为某些节点存在数据热点等原因而造成流量是不均衡的。

通过对RootServer管理的所有tablet数据分片所在位置信息Metadata进行统计,我们发现各个ChunkServer上的tablet数据量差异不大,这同时也说明扩容加入新的Server之后,集群的Rebalance是有效的(后来我们在其他应用的集群也发现了存在数据不均衡问题,本文暂不解释)。

尽管排除了数据不均衡问题,流量不均衡又存在如下的几种可能性:

  1. 存在访问热点:比如热销的商品,这些热点数据会导致ChunkServer成为访问热点,造成了负载不均;
  2. 请求差异性较大:系统负载和处理请求所耗费的CPU\Memory\磁盘IO资源成正比,而资源的耗费一般又和处理的数据量是成正比的,即可能是因为存在某些大用户而导致没有数据访问热点的情况下,负载仍然是不均衡的。

经过如上的分析至少已经确定ChunkServer流量不均衡问题和步骤4紧密相关的,而目前所采用的tablet副本选择的策略是随机法。一般而言随机化的负载均衡策略简单、高效、无状态,结合业务场景的特点进行分析,热点数据所占的比例并不会太高,把ChunkServer上的Tablet按照访问次数进行统计也发现并没有超乎想象的“大热点”,基本服从正太分布

可见热点Tablet虽访问频率稍高对负载的贡献率相对较大,但是热点tablet的占比很低,相反所有非热点tablet对负载的贡献率总和还是很高的,这种情况就好比“长尾效应”[3]。

负载均衡算法设计

如果把热点ChunkServer上非热点Tablet的访问调度到其他Server,是可以缓解流量不均问题的,因此我们设计了新的负载均衡算法为以实时统计的ChunkServer上所有tablet的访问次数为Ticket,每次对Tablet的读请求会选择副本中得票率最低的ChunkServer。

同时考虑到流量不均衡的第二个原因是请求的差异较大问题,ChunkServer对外提供的接口分为Get和Scan两种,Scan是扫描一个范围的所有行数据,Get是获取指定一行数据,因此两种访问方式的次数需要划分赋予不同的权重(α,β)参与最终Ticket的运算:


除此之外,简单的区分两种访问模式还是远远不够的,不同的Scan占用的资源也是存在较大差异的,引入平均响应时间(avg_time)这个重要因素也是十分必要的:


负载均衡算法要求具有自适应性和强的实时性,一方面新的访问要实时累积参与下次的负载均衡的调度,另一方面历史权重数据则需要根据统计周期进行非线性的衰减(y 衰减因子),减少对实时性的影响:


采用新的算法后,很好的缓解了负载不均衡的问题,整体负载提升了1倍,整体QPS吞吐提升到了8w。

小结

负载均衡问题是老生常谈的问题,解决不好就会出现“短板效应”,更甚至引发分布式系统中的连锁反应即“雪崩”,从而演化成系统的灾难。负载均衡的算法也层出不穷,有的出于成本最优,有的是为了最小延迟,有的则是最大化系统吞吐,目的不同算法自然各异,不存在包治百病的良方,并不是越复杂的算法越有效[4],要综合考虑算法所需数据获取的Overhead,更多的是遵循“简单实用”的法则,根据业务场景进行分析和尝试。

正是这种灵活性的策略,对我们的系统设计提出了新的需求,要有一定的机制来监控和验证问题:比如可以实时获取系统运行的各种内部状态和数据,允许选择不同负载均衡算法进行试验等。

Update1:看到楼下网友专业方面的提问,@Leverly 已经进行了回复。有更多交流,不妨直接讨论。共享:)!

3月2日Update2:图2.2已更换(原图右边显示不完全,应为“A,E,G,H,I")。

参考文献

1.OceanBase : http://oceanbase.taobao.org/

2.Buckets effect: http://www.baike.com/wiki/%E6%9C%A8%E6%A1%B6%E7%90%86%E8%AE%BA

3.Long Tail: http://en.wikipedia.org/wiki/The_long_tail

4.http://www.cs.usask.ca/faculty/eager/loadsharing.pdf

欢迎 @CSDN云计算微博参与讨论,了解更多云信息。

负载均衡的发展基础就是负载均衡算法。那么针对不同的服务器我们也会采用不同的负载均衡算法,因为他们所具备的和要求的功能各不相同。那么我们现在就来详细了解一下这方面的知识。希望能让大家从中得到需要的东西。

服务器负载均衡算法有很多(持续性的和非持续性的),包括轮循算法、最少连接算法、响应时间算法、散列算法、最少连接失误算法,链路带宽算法等等。

此外实际服务器(RealServer)可以被分配不同的加权值来调整被分配的流量。比如性能高的大型服务器可配置较大的加权值,而为性能较低的小型服务器设置较小的加权值。为了避免服务器因过载而崩溃,可为实际服务器指定最大连接阈值来避免该服务器过载。任何服务器可被指定为另一台服务器的备份服务器或溢出服务器,从而进一步保证了应用可用性。

非持续性算法(Non-Persistent):

一个客户端的不同的请求可能被分配到一个实际服务组中的不同的实服务器上进行处理。

主要有轮循算法、最少连接算法、响应速度算法等。

轮循算法(RoundRobin):

说明:每一次来自网络的请求轮流分配给内部中的每台服务器,从1至N然后重新开始。

举例:此种负载均衡算法适合于服务器组中的所有服务器都有相同的软硬件配置并且平均服务请求相对均衡的情况;

最少连接算法(LeastConnection):

说明:客户端的每一次请求服务在服务器停留的时间都可能会有较大的差异,随着工作时间的加长,如果采用简单的轮循或随机均衡算法,每一台服务器上的连接进程可能会产生极大的不同,这样的结果并不会达到真正的负载均衡。最少连接数均衡算法对内部中有负载的每一台服务器都有一个数据记录,记录的内容是当前该服务器正在处理的连接数量,当有新的服务连接请求时,将把当前请求分配给连接数最少的服务器,使均衡更加符合实际情况,负载更加均衡。

举例:此种负载均衡算法适合长时间处理的请求服务。

响应速度算法(ResponseTime):

说明:负载均衡设备对内部各服务器发出一个探测请求(例如Ping),然后根据内部中各服务器对探测请求的最快响应时间来决定哪一台服务器来响应客户端的服务请求。

举例:此种负载均衡算法能较好地反映服务器的当前运行状态,但最快响应时间仅仅指的是负载均衡设备与服务器间的最快响应时间,而不是客户端与服务器间的最快响应时间。

持续性算法(Persistent):

从一个特定的客户端发出的请求都被分配到一个实服务组中的同一个实服务器上进行处理。

主要包括的负载均衡算法有:

A.基于IP的算法

Persistent IP(pi):基于用户IP地址来选择服务器。

Hash IP(hi):基于用户IP地址的HASH值,来选择服务器

Consistent Hash IP(chi):基于列表IP来选择服务器

B.基于报头/请求的算法

HashHeader(hh):基于用户请求报中HTTP报头来选择服务器;

PersistentHostname(ph):基于用户请求报中HTTP报头的Hostname的HASH值,来选择服务器;

PersistentURL(pu):基于对URITag和值的静态对应关系来选择服务器。

SSLSessionID(sslsid):基于SSL会话ID来选择服务器。

C.基于Cookie的负载均衡算法

PersistentCookie(pc):选择服务器基于用户请求包用CookieName/Value的静态对应关系;

HashCookie(hc):选择服务器基于用户请求包用CookieName/Value的Hash值对应关系;

InsertCookie(ic):选择服务器基于负载均衡器向服务器响应包中插入Cookie;

Re-writeCookie(rc):选择服务器基于负载均衡器向服务器响应包中重写Cookie值。(必须为重写指定Cookie值的偏移量)

感觉作者对此文章写得很好,为了方便以后自己能够常看,故此搬到这里来。
    原文出处:http://network.51cto.com/art/201005/197952.htm


0 0