负载均衡的常用算法

在集群中,假设有五台服务器,他们之间的地位相同(主备模式不是我们要讨论的内容),都对外提供服务。当浏览器大量请求到达时,如何决定哪个请求到达哪个服务器上,这就是我们这次讨论的核心内容。

负载均衡的策略分为应用服务器和分布式缓存集群两种适应场景。

为什么这么分呢?简单的说,应用服务器只需要转发请求就可以了。但分布式缓存集群,比如redis、Memcached等,更多的是需要再次读取数据的。也正是因为这样,当新加入一台机器后,要尽量对整个集群的影响小。

1、应用服务器

NO.1—— Random 随机

这是最简单的一种,使用随机数来决定转发到哪台机器上。

优点:简单使用,不需要额外的配置和算法。
缺点:随机数的特点是在数据量大到一定量时才能保证均衡,所以如果请求量有限的话,可能会达不到均衡负载的要求。

NO.2—— Round Robin 轮询

这个也很简单,请求到达后,依次转发,不偏不向。每个服务器的请求数量很平均。

缺点:当集群中服务器硬件配置不同、性能差别大时,无法区别对待。引出下面的算法。

NO.3—— Weighted Round Robin 加权轮询

这种算法的出现就是为了解决简单轮询策略中的不足。在实际项目中,经常会遇到这样的情况。

比如有5台机器,两台新买入的性能等各方面都特别好,剩下三台老古董。这时候我们设置一个权重,让新机器接收更多的请求。物尽其用、能者多劳嘛!

这种情况下,“均衡“就比较相对了,也没必要做到百分百的平均。

NO.4—— Least Connections 最少连接

这是最符合负载均衡算法的一个。需要记录每个应用服务器正在处理的连接数,然后将新来的请求转发到最少的那台上。

NO.5—— Source Hashing 源地址散列

根据请求的来源ip进行hash计算,然后对应到一个服务器上。之后所有来自这个ip的请求都由同一台服务器处理。

2、分布式缓存集群

好了,有了前面的基础,再看分布式缓存集群就简单多了。我们只需要多考虑两点就够了。

NO.1—— 取模

这是最简单但最不实用的一个。

以redis为例,假设我们有5台机器,要想取模肯定先得转换为数字,我们将一个请求的key转成数字(比如CRC16算法那),比如现在五个请求转换成的数字后对5取模分别为0、1、2、3、4,正好转发到五台机器上。

这时意外来了,其中一台宕机了,现在集群中还有4台。之后再来请求只能对4取模。问题就暴露出来了,那之前按照5取模的数据命中的机率大大降低了,相当于每宕机一台,之前存入的数据几乎都不能用了。

因此,不推荐此种做法。

NO.2—— 哈希

这种算法叫哈希有些笼统了,具体可以分为ip哈希和url哈希(类似原地址散列)。这里就不多说了。重点说下redis中的设计。

redis中引入了哈希槽来解决这一问题。16384个哈希槽,每次不再对集群中服务器的总数取模,而是16384这个固定的数字。然后将请求分发。这样就可以避免其中一台服务器宕机,原有数据无法命中的问题。

NO.3—— 一致性哈希

终于到重头戏了,不过有了前面的介绍,这个也就不难理解了。
一致性哈希在memcached中有使用,通过一个hash环来实现key到缓存服务器的映射。

这个环的长度为2^32,根据节点名称的hash值将缓存服务器节点放在这个hash环上。如下图中的node1、node2等。

这时要保存的数据key仍旧进行hash运算,运算之后的值会落在这个hash环上的某一处(图中粉色的节点),当然这还没结束,因为他还没有落到node上。之后这个粉色的节点会沿顺时针落到离他最近的node上,over。

这里写图片描述

改进

当其中某个结点宕机后,比如node4,这时如果有结点落在了node2和node4之间,本来应该归为node4的,但这时候他宕机了,就都放在了下一个node3中。

这时,每个结点的数据量就会有很大出入了,平衡性很难保证。因此,引入“虚拟结点”。

虚拟结点是实际结点在hash空间的复制品,为了保证平衡性,一个实际node被划分成了若干个虚拟node。

如下图所示:

服务器之间的交错关系会改变,每个虚拟node之间的相对关系是不一定的,比如每个node1的虚拟节点后面可以是node2的也可以跟node3的。

此时,如果红色的node宕机了,那么将要落在这台机器上的数据可能落到蓝色,也可能是绿色的。这就保证了一定程度的平衡性。

这里写图片描述

posted @ 2016-07-22 17:02  Sherry&Yang  阅读(3840)  评论(0编辑  收藏  举报