谈谈一致性哈希算法及其 Golang 实现(含负载均衡算法概述)

一、概述

  本篇博文我们将会谈一谈一些的常见负载均衡算法,然后重点讨论一下 一致性哈希算法 的适用范围和算法思想,最后提供一个我自己写的 Golang 版本的实现(做 Lab 时顺手写)。

  博客内所有文章和代码均为 原创,所有示意图均为 原创,若转载请附原文链接。


二、负载均衡算法

2.1 概述

  在分布式系统中,为了避免对系统中的某一台服务器进行集中地访问而导致该服务器出现被流量压垮的现象,一般都会采用相关的负载均衡算法来对流量进行分散。而对于负载均衡算法的具体应用进一步细化的话,一般比较常见的是对外网访问的流量进行负载均衡,或者在我们经常接触的微服务当中,也经常会将服务注册到服务中心中,然后其他服务会通过服务中心来查询自己所需调用服务的地址后再进行调用,这样就通过服务中心对访问服务的流量进行了负载均衡,又或者在分布式存储系统中,我们为了提升存储系统的性能,经常会采用分片存储的方式来对数据进行存储,这样做最大意义在于当将数据按照不同类别进行分片存储后,就可以将不同片区的数据分散到不同的服务器上进行存储,一方面可以使后期的数据查询等操作并行进行,另一方面因为每个服务器仅存储部分片区的数据,所以查询数据的速度也会大大提升。


2.2 轮询算法

  负载均衡的众多算法中最简单的就是 轮询算法 ,顾名思义这个算法就是通过轮询的方式将流量绝对平均的分发给每一台服务器,这种算法最后的效果就是集群中的所有服务器会接收到绝对相同量级的流量访问,比较适用于集群中所有机器的性能大致相同时。

2.3 随机算法

  随机算法 跟上面的轮询算法实现难度差不多,实现方式也是顾名思义,就是通过随机的方式将流量进行分发,但是如果有学过概率论的话应该会有一些印象,这种方式最终的分发效果其实是类似于轮询算法的(当随机分配的数量趋于无穷大时,分配趋于平均分配)。

2.4 随机轮询算法

  这个 随机轮询算法 我也是从网上了解到的,根据网上的描述它的实现方式其实跟轮询算法是大同小异的,它虽然将轮询法和随机法进行了结合,但也仅仅对每轮轮询的开始节点进行随机,而接下来的分发也还是按照轮询算法的方式进行。

2.5 加权轮询算法

  加权轮询算法 是 Nginx 的默认负载均衡算法,上面提到的几种算法都适用于当集群中的机器性能大致相同时,而这种算法比较适合于当集群中的机器存在性能差异时进行使用,比如对于性能较低的机器我们可以将其权值设置的小一点,从而在轮询时少分给它一些流量,而对于性能较高的机器我们可以调大其权值,从而在轮询时多分发给它一些流量。这种算法相对于上面几种算法可以在集群中机器存在性能差异时,最大化发挥集群中机器的性能。

2.6 哈希算法

  哈希算法 不只是在负载均衡领域,在一些编程领域我们也会经常接触到,它的主要思想就是对发送请求的 IP 地址或其它信息进行哈希,然后将求取的哈希值取模当前集群中的机器数量,最后根据取模值将其分发给特定的机器来处理,这样做的好处是可以保证发送请求的客户端的所有请求会被持续分发给同一个服务器进行处理,因此比较适用于缓存领域。

三、一致性哈希算法

3.1 适用场景

  当我们在设计分布式缓存系统时经常需要考虑的一个问题就是如何才能提升系统的 容错性可扩展性 以及 缓存命中率 ,怎么理解这三点呢,首先容错性是指当分布式缓存系统中一台或多台服务器不可用时,系统能够保持正常的运转,而可扩展性就是当我们为了提升系统性能而添加新的服务器时,系统是否在添加新服务器后正常工作且性能有所提升,最后的缓存命中率是建立在当我们持续的将同一个客户端的请求发送给同一台服务器进行处理时,该台服务器中会缓存该客户端近期所需的数据,所以缓存命中的几率会大大提升。

  首先谈一些如何实现系统的 容错性 ,要提升系统的容错性我们就要保证当系统中一台或多台服务器发生故障后,发生故障的机器所负责的数据能够重新分配到无故障的机器中,从而让外部感受不到系统内部发生的故障。其次当我们要提升系统的 可扩展性 时,其实也就是在考虑如何能够在集群正常运行时动态加入机器,所谓动态加入是指集群能够保证当有新机器加入时,集群能够将属于原集群中机器的部分数据分配给新机器来进行处理,降低集群中每台机器所需处理的平均缓存数据量,从而达到提升系统性能的目的。最后,要提升系统的 缓存命中率 就要保证同一个客户端发送的请求能够持续的被分发给同一台服务器来进行处理。

  容错性和可扩展性实现的思路大致如上,但是其实现才是至关重要的。如果使用上面的几种负载均衡算法来进行实现,可能会适得其反。首先就用性能较好的哈希算法来举例,因为相对于其它的几种算法哈希算法能够最大限度的提升缓存的命中率。我们知道对于哈希算法其每次对于请求的处理都是哈希地址等信息后取模,然后再根据取模值将其分配给特定的服务器来进行处理,那么当我们集群中移除(容错)或增加新(扩展)的机器时,所有客户端请求所对应的服务器都会被重新计算(因为集群中的机器数量发生变化,因此哈希取模值也会发生变化),因此会造成大量的缓存键被重新分配,从而导致大量的客户端请求 缓存无法命中

  那么我们有没有什么好的方法来解决这个问题呢,这里就可以使用到 一致性哈希算法 ,也成 哈希环 算法。

3.2 算法思想

  因为网上对一致性哈希算法思想的分析很多,所以这里我就不做赘述,但是总结起来其对于哈希算法优化的思想就是将原 哈希算法 点对点映射 的方式优化为 点对线的映射 的方式 ,核心思想就是将 客户端地址的哈希值和服务端地址的哈希值放到同一个哈希环上 。在哈希算法中我们对客户端的地址哈希后取余,然后将其映射到一个单一的服务器,而正是这种客户端点对服务端点的这种点对点映射方式,造成了当服务端机器数量变化时取模值发生变化,从而导致大量的客户端被重定向。但如果我们选择使用一致性哈希的客户端点对服务端线的方式进行映射,让每台服务器不再仅仅只映射单个哈希取模的值而是映射一段哈希取模值的区域,就会增加每台服务

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值