详解Consistent Hashing算法

开发 后端 算法
在做服务器负载均衡时候可供选择的负载均衡的算法有很多,包括: 轮循算法(Round Robin)、哈希算法(HASH)、最少连接算法(Least Connection)、响应速度算法(Response Time)、加权法(Weighted )等。

在做服务器负载均衡时候可供选择的负载均衡的算法有很多,包括: 轮循算法(Round Robin)、哈希算法(HASH)、最少连接算法(Least Connection)、响应速度算法(Response Time)、加权法(Weighted )等。其中哈希算法是最为常用的算法.

典型的应用场景是: 有N台服务器提供缓存服务,需要对服务器进行负载均衡,将请求平均分发到每台服务器上,每台机器负责1/N的服务。

常用的算法是对hash结果取余数 (hash() mod N ):对机器编号从0到N-1,按照自定义的 hash()算法,对每个请求的hash()值按N取模,得到余数i,然后将请求分发到编号为i的机器。但这样的算法方法存在致命问题,如果某一台机器宕机,那么应该落在该机器的请求就无法得到正确的处理,这时需要将当掉的服务器从算法从去除,此时候会有(N-1)/N的服务器的缓存数据需要重新进行计算;如果新增一台机器,会有N /(N+1)的服务器的缓存数据需要进行重新计算。对于系统而言,这通常是不可接受的颠簸(因为这意味着大量缓存的失效或者数据需要转移)。那么,如何设计一个负载均衡策略,使得受到影响的请求尽可能的少呢?

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

1、Consistent Hashing算法描述

下面以Memcached中的Consisten Hashing算法为例说明(参考memcached的分布式算法 )。

由于hash算法结果一般为unsigned int型,因此对于hash函数的结果应该均匀分布在[0,232 -1]间,如果我们把一个圆环用232 个点来进行均匀切割,首先按照hash(key)函数算出服务器(节点)的哈希值, 并将其分布到0~232 的圆上。

用同样的hash(key)函数求出需要存储数据的键的哈希值,并映射到圆上。然后从数据映射到的位置开始顺时针查找,将数据保存到找到的***个服务器(节点)上。

 

Consistent hashing,memcached,load balancing,负载均衡,算法,key-value store

Consistent Hashing原理示意图

 

1. 新增一个节点:只有在圆环上新增节点到逆时针方向的***个节点之间的数据会受到影响(增加节点顺时针的***个节点的信息需要迁移到增加节点上)。

2. 删除一个节点:只有在圆环上原来删除节点到 逆时针 方向的***个节点之间的数据会受到影响(删除节点的信息需要迁移到顺时针的***个节点上) ,因此通过Consistent Hashing很好地解决了负载均衡中由于新增节点、删除节点引起的hash值颠簸问题。

 

Consistent hashing,memcached,load balancing,负载均衡,算法,key-value store

Consistent Hashing添加服务器示意图

 

虚拟节点(virtual nodes): 之所以要引进虚拟节点是因为在服务器(节点)数较少的情况下(例如只有3台服务器),通过hash(key)算出节点的哈希值在圆环上并不是均匀分布的(稀疏的),仍然会出现各节点负载不均衡的问题。虚拟节点可以认为是实际节点的复制品(replicas),本质上与实际节点实际上是一样的(key并不相同)。引入虚拟节点后,通过将每个实际的服务器(节点)数按照一定的比例(例如200倍)扩大后并计算其hash(key)值以均匀分布到圆环上。在进行负载均衡时候,落到虚拟节点的哈希值实际就落到了实际的节点上。由于所有的实际节点是按照相同的比例复制成虚拟节点的,因此解决了节点数较少的情况下哈希值在圆环上均匀分布的问题。

 

Consistent hashing,memcached,load balancing,负载均衡,算法,key-value store

 

虚拟节点对Consistent Hashing结果的影响

从上图可以看出,在节点数为10个的情况下,每个实际节点的虚拟节点数为实际节点的100-200倍的时候,结果还是很均衡的。

2、Consistent Hashing算法实现:

文章Consistent Hashing 中描述了Consistent Hashing的Java实现,很简洁。

 

  1. import java.util.Collection;  
  2. import java.util.SortedMap;  
  3. import java.util.TreeMap;  
  4.  
  5. public class ConsistentHash<T> {  
  6.  
  7.  private final HashFunction hashFunction;  
  8.  private final int numberOfReplicas;  
  9.  private final SortedMap<Integer, T> circle = new TreeMap<Integer, T>();  
  10.  
  11.  public ConsistentHash(HashFunction hashFunction, int numberOfReplicas,  
  12.      Collection<T> nodes) {  
  13.    this.hashFunction = hashFunction;  
  14.    this.numberOfReplicas = numberOfReplicas;  
  15.  
  16.    for (T node : nodes) {  
  17.      add(node);  
  18.    }  
  19.  }  
  20.  
  21.  public void add(T node) {  
  22.    for (int i = 0; i < numberOfReplicas; i++) {  
  23.      circle.put(hashFunction.hash(node.toString() + i), node);  
  24.    }  
  25.  }  
  26.  
  27.  public void remove(T node) {  
  28.    for (int i = 0; i < numberOfReplicas; i++) {  
  29.      circle.remove(hashFunction.hash(node.toString() + i));  
  30.    }  
  31.  }  
  32.  
  33.  public T get(Object key) {  
  34.    if (circle.isEmpty()) {  
  35.      return null;  
  36.    }  
  37.    int hash = hashFunction.hash(key);  
  38.    if (!circle.containsKey(hash)) {  
  39.      SortedMap<Integer, T> tailMap = circle.tailMap(hash);  
  40.      hash = tailMap.isEmpty() ? circle.firstKey() : tailMap.firstKey();  
  41.    }  
  42.    return circle.get(hash);  
  43.  }  
  44.  

 

责任编辑:金贺 来源: ITEYE博客
相关推荐

2018-08-08 15:51:44

Hash分布式算法

2011-08-12 12:34:27

Oracle数据库consistent

2022-02-04 21:56:59

回溯算法面试

2010-04-20 13:36:17

负载平衡

2017-11-22 14:20:07

前端JavaScript排序算法

2010-01-06 16:33:50

.Net Framew

2010-09-09 14:52:56

CSS盒模型

2017-03-17 14:18:34

JavaScript算法问题详解

2009-08-25 17:41:51

C#开发排序算法

2020-09-09 10:20:48

GraphSAGE神经网络人工智能

2010-01-11 15:01:55

VB.NET冒泡排序

2024-04-18 15:44:20

2022-03-03 19:31:31

队列算法Harmony

2015-08-20 11:01:22

Java虚拟机GC算法种类

2018-07-06 11:39:40

2022-03-18 06:32:43

递归Python算法

2020-10-14 08:32:08

算法递归面试

2018-07-25 12:00:21

2023-05-10 08:00:00

聚类分析数据分析聚类算法

2015-06-16 10:39:43

NoSQL分布式算法
点赞
收藏

51CTO技术栈公众号