分布式算法(一致性Hash算法)

分布式算法

在做服务器负载均衡时候可供选择的负载均衡的算法很多, 包括: 轮询, 哈希, 最少连接, 响应速度, 加权。其中哈希算法是最为常用的算法。典型的应用场景是: 有N台服务器提供缓存服务, 需要对服务器进行负载均衡, 将请求平均的分发到每台服务器上, 每台机器负责1/N的服务。常用的算法是对hash结果取余数(hash() mod N): 对机器编号从0到N-1, 按照自定义的hash()算法, 对每个请求的hash()值按N取模, 得到余数I, 然后将请求分发到编号为i的机器。但这样的方法存在致命的问题, 如果某一台机器宕机, 那么应该落在该机器的请求就无法得到正确的处理, 这时需要将宕掉的服务器从算法中去除, 此时候会有(N-1)/N的服务器的缓存数据需要重新进行计算; 对于系统而言, 这通常是不可接受的。那么, 如何设计一个负载均衡策略, 使得收到影响的请求尽可能的少呢?

Memcached, Key-Value Store, Bittorrent DHT, LVS中都采用了Consistent Hashing算法, 可以说Consistent Hashing是分布式系统负载均衡的首选算法

分布式缓存问题

在大型web应用中, 缓存可算是当今的一个标准开发配置。在大规模的缓存应用中, 应运而生了分布式缓存系统。key-value如何均匀的分散到集群中? 最常规的方式莫过于hash取模的方式。比如集群中可用机器适量为N, 那么key值为K的数据请求很简单的应该路由到hash(K) mod N对应的机器。在一些高速发展的web系统中, 这样的解决方案仍然有些缺陷。随着系统访问压力的增长, 缓存系统不得不通过增加机器节点的方式提高集群的响应速度和数据承载量。增加机器意味着按照hash取模的方式, 在增加机器节点的这一时刻, 大量的缓存命不中, 缓存数据需要重新建立, 甚至是进行整体的缓存数据迁移, 瞬间会给DB带来极高的系统负载, 甚至导致DB服务器宕机。就没有办法解决hash取模的方式带来的问题吗?

假设有一个网站, 最近发现随着流量增加, 服务器压力越来越大, 之前直接读写数据库的方式不太给力了, 于是想引入Memcached作为缓存机制。现在一共有三台机器可以作为Memcached服务器, 如下图所示:

最简单的策略是将每一次Memcached请求随机发送到一台Memcached服务器, 但是这种策略会带来两个问题: 一是同一份数据可能被存在不同的机器上而造成数据冗余, 而是有可能某数据已经比缓存但是访问却没有命中, 因为无法保证对相同key的所有访问都被发送到相同的服务器. 因此, 随机策略无论是时间效率还是空间效率都非常不好。要解决上诉问题只需要做到如下一点: 保证对相同key的访问会被发送到相同的服务器。很多方法可以实现这一点, 最常用的方法是计算哈希。例如对于每次访问, 可以按如下算法计算其哈希值:

h=Hash(key)%3

其中Hash是一个从字符串到正整数的哈希映射函数。这样, 如果将Memcached Server分别编号为0, 1, 2, 那么就可以根据上式和key计算出服务器编号h, 然后取访问。

这个方法虽然解决了上面提到的两个问题, 但是存在一些其它问题。如果将上述方法抽象, 可以认为通过:

h=Hash(key)%N

这个算式计算每个key的请求应该被发送到哪台服务器, 其中N为服务器的台数, 并且服务器按照0-(N-1)编号。这个算法的问题在于容错性和扩展性不好。所谓容错性是指当系统中某一个或几个服务器变得不可用时, 整个系统是否可以正确高效运行; 而扩展性是指当加入新的服务器后, 整个系统是否可以正确高效运行。

现假设有一台服务器宕机了, 那么为了填补空缺, 要将宕机的服务器从编号列表中移除, 后面的服务器按顺序前移一位并将其编号值减一, 此时每个key就要按h=Hash(key)%(N-1)重新计算; 同样, 如果新增了一台服务器, 虽然原有服务器编号不用改变, 但是要按h=Hash(key)%(N+1)重新计算哈希值。因此系统中一旦有服务器变更, 大量的key会被重定位到不同的服务器从而造成大量的缓存不命中。而这种情况在分布式系统中是非常糟糕的。

一个设计良好的分布式哈希方案应该具有良好的单调性(弹性), 即服务节点的增减不会造成大量哈希重定位。一致性哈希算法就是这样一种哈希方案。

Hash算法的一个衡量指标就是单调性(Monotonicity), 定义如下: 单调性是指如果已经有yixie 内容通过哈希分派到了相应的缓冲中, 又有新的缓冲加入到系统中。哈希的结果应该能够保证原有已分配的内容可以被映射到新的缓冲中去, 而不会被映射到旧的缓冲集合中的其他缓冲区。

容易看到, 上面的简单hash算法hash(object)%N难以满足单调性要求

一致性哈希算法的理解

算法简述

一致性哈希算法(Consistent Hashing Algorithm)是一种分布式算法, 常用于负载均衡。Memcached client也选择这种算法, 解决将key-value均匀分配到众多Memcached server上的问题。它可以取代传统的取模操作, 解决取模操作无法应对增删Memcached Server的问题(增删server会导致同一个key, 在get操作时分配不到数据真正存储的server, 命中率急剧下降)。

一致性哈希将整个哈希值空间组织成一个虚拟的圆环, 如假设某哈希函数H的值空间为0-(2^32)-1(即哈希值是一个32位无符号整形), 整个哈希空间环如下:

整个空间按顺时针方向组织。0和(2^32)-1在零点中方向重合。

下一步将各个服务器使用H进行一个哈希, 具体可以选择服务器的ip或主机名作为关键字进行哈希, 这样每台机器就能确定其在哈希环上的位置, 这里假设将上文中三台服务器使用ip地址哈希后再环空间的位置如下:

接下来使用如下算法定位数据访问到响应服务器: 将数据key使用相同的函数H计算出哈希值h, 根据h确定此数据再环上的位置, 从此位置沿环顺势针”行走” 第一台遇到的服务器就是其应该定位到的服务器

例如我们有A, B, C, D四个数据对象, 经过哈希计算后, 在环空间上的位置如下:

根据一致性哈希算法, 数据A会被定位到Server 1上, D被定位到Server 3上, 而B, C分别被定位到Server 2上

容错性与可扩展性分析

现假设Server 3宕机了:

可以看到此时A, C, B不会受到影响, 只有D节点被重定位到Server 2。一般的, 在一致性哈希算法中, 如果一台服务器不可用, 则受影响的数据仅仅是此服务器到其环空间中前一台服务器(即顺时针方向行走遇到的第一台服务器)之间数据, 其它不会受到影响。

下面考虑另外一种情况, 如果在系统中增加一台服务器Memcached Server 4

此时A, D, C不受影响, 只有B需要重定位到新的Server 4。一般的, 在一致性哈希算法中, 如果增加一台服务器, 则受影响的数据仅仅是新服务器到其环空间中前一台服务器(即顺着逆时针方向行走遇到的第一台服务器)之间数据, 其他不会受到影响。

一致性哈希算法对于节点的增减都只需重定位换空间的一小部分数据, 具有较好的容错性和可扩展性

虚拟节点

一致性哈希算法在服务节点太少时, 容易因为节点分布不均匀而造成数据倾斜问题。例如我们的系统中有两台服务器, 其环分布如下:

此时必然造成大量数据集中到Server1, 而只有极少量会定位到Server 2上。为了解决这种数据倾斜问题, 一致性哈希算法引入了虚拟节点机制, 即对每一个服务节点计算多个哈希, 每个计算结果位置都放置一个此服务节点, 称为虚拟节点。具体做法可以在服务器ip或主机名的后面增加编号来实现。例如上面的情况。我们决定为每台服务器计算三个虚拟节点, 于是可以分别计算”Memcached Server 1#1”, “Memcached Server 1#2”, “Memcached Server 1#3”, “Memcached Server 2#1”, “Memcached Server 2#2”, “Memcached Server 2#3”的哈希值, 于是形成六个虚拟节点

Consistent Hashing最大限度地抑制了hash键地重新分布。另外要取得比较好地负载均衡地效果, 往往在服务器数量比较少的时候需要增加虚拟节点来保证服务器能均匀的分布在圆环上。因为使用一般的hash方法, 服务器的映射地点的分布非常不均匀。使用虚拟节点的思想, 为每个物理节点(服务器)在圆上分配100~200个点。这样就能抑制分布不均匀, 最大限度地减少服务器增减时地缓存重新分布。用户数据映射在虚拟节点上, 就表示用户数据真正存储位置时在该虚拟节点代表地实际物理服务器上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值