consistent hashing

consistent hashing 算法思想是:首先求出服务器(节点)的哈希值,并将其配置到0~2^32的圆上。然后用同样的方法求出 存储数据的键的哈希值,并映射到圆上。然后从数据映射到的位置开始顺时针查找,将数据保存到找到的第一个服务器上。如果超过2^32仍然找不到服务器,就 会保存到第一台服务器上。下面有一张比较经典的图,直接用过来,不修改了。

     Consistent Hashing原理示意图

        图一  Consistent Hashing原理示意图

     这里有四台服务器,我们假设增加一台服务器Node5,可以看到,它影响的数据只是在增加Node5逆时针方向的数据会受到影响。同样,删除其中一台服务器,例如删除服务器node4,那么影响的数据也只是node4上缓存的数据。

    Consistent Hashing添加服务器示意图

   图二 Consistent Hashing添加服务器

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

 

  图三 虚拟节点倍数- 物理节点数关系图

      x轴表示的是需要为每台物理服务器扩展的虚拟节点倍数(scale),y轴是实际物理服务器数,可以看出,当物理服务器的数量很小时,需要更大的虚拟节 点,反之则需要更少的节点,从图上可以看出,在物理服务器有10台时,差不多需要为每台服务器增加100~200个虚拟节点才能达到真正的负载均衡。

下面是一个简单的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(  
  12.       HashFunction hashFunction, //hash算法   
  13.       int  numberOfReplicas, //虚拟节点数   
  14.       Collection<T> nodes//物理节点   
  15.    ) {  
  16.    this .hashFunction = hashFunction;  
  17.    this .numberOfReplicas = numberOfReplicas;  
  18.   
  19.    for  (T node : nodes) {  
  20.      add(node);  
  21.    }  
  22.  }  
  23.   
  24.  public   void  add(T node) {  
  25.    for  ( int  i =  0 ; i < numberOfReplicas; i++) {  
  26.      circle.put(hashFunction.hash(node.toString() + i), node);  
  27.    }  
  28.  }  
  29.   
  30.  public   void  remove(T node) {  
  31.    for  ( int  i =  0 ; i < numberOfReplicas; i++) {  
  32.      circle.remove(hashFunction.hash(node.toString() + i));  
  33.    }  
  34.  }  
  35.    
  36. //关键算法   
  37.  public  T get(Object key) {  
  38.    if  (circle.isEmpty()) {  
  39.      return   null ;  
  40.    }  
  41.    int  hash = hashFunction.hash(key);  
  42.    if  (!circle.containsKey(hash)) {  
  43.      SortedMap<Integer, T> tailMap = circle.tailMap(hash);  
  44.      hash = tailMap.isEmpty() ? circle.firstKey() : tailMap.firstKey();  
  45.    }  
  46.    return  circle.get(hash);  
  47.  }  
  48.   

本文转载自: http://blog.csdn.net/lovingprince/archive/2009/10/09/4645448.aspx

猜你喜欢

转载自langwangff.iteye.com/blog/648087
今日推荐