一致性哈希

一致性哈希在分佈式系統中被不少的使用,好比說memcached就是使用一致性哈希來作的。學習一下這個一致性哈希算法。html

下面這篇博客利用圖解的形式,將一致性哈希算法講述的很是清楚:java

博客:http://blog.codinglabs.org/articles/consistent-hashing.htmlnode

參考代碼,下面我列出了java和c#的兩個代碼實現,能夠經過讀代碼更深入的去理解一下這個算法。 代碼:web

根據上述文章和代碼,仿照着寫了一個粗略版本的一致性哈希算法。算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
public delegate int HashFunction( string val);
 
public class ConsistentHash<T> where T : class
{
     //this value used for generate virtual nodes
     private int _replica;
     //Hash fuction used to calculate hash code base on a string
     private HashFunction getHashCode;
     //image this as a big circle which store the node
     private SortedDictionary< int , T> circle = new SortedDictionary< int , T>();
 
     public ConsistentHash(HashFunction hashFunc, ICollection<T> nodes, int replicaNum = 100)
     {
         _replica = replicaNum;
         getHashCode = hashFunc;
         Init(nodes);
     }
 
     public void Add(T node)
     {
         for ( int i = 0; i < _replica; i++)
         {
             int hash = getHashCode(node.GetHashCode().ToString() + i);
             circle[hash] = node;
         }
     }
 
     public void Remove(T node)
     {
         for ( int i = 0; i < _replica; i++)
         {
             int hash = getHashCode(node.GetHashCode().ToString() + i);
             circle.Remove(hash);
         }
     }
 
     public T GetNode( object key)
     {
         if (key == null )
             return null ;
         int hashcode = getHashCode(key.GetHashCode().ToString());
         int firstNode = GetFirst(circle.Keys.ToArray() , hashcode);
         return circle[firstNode];
     }
 
     /// <summary>
     /// use binary search to search the first value in keys array
     /// which bigger than hashcode
     /// if not exist return first key in keys array
     /// </summary>
     /// <param name="keys">key array</param>
     /// <param name="hashcode"></param>
     /// <returns></returns>
     private int GetFirst( int [] keys, int hashcode)
     {
         int beg = 0, end = keys.Length - 1;
         circle.Keys.CopyTo(keys, keys.Length);
         if (hashcode < keys[beg] || hashcode > keys[end])
             return keys[0];
         while (end > beg)
         {
             int mid = (end + beg) / 2;
             if (keys[mid] >= hashcode)
                 end = mid;
             else
                 beg = mid;
         }
         return keys[end];
     }
 
     private void Init(ICollection<T> nodes)
     {
         foreach (T node in nodes)
         {
             Add(node);
         }
     }
}
  • 沒有使用那個默認的Hash code,由於默認的哈希實現可能不夠好。最好可以使用本身能夠控制的一個好的哈希算法。
  • _replica變量就是每個結點對應的虛擬節點的個數。虛擬節點是爲了解決數據傾斜的問題,也就是說節點分佈的不夠均勻致使最後分配到每個節點上的負載不均衡。理論上來講若是實際節點越少,則須要的虛擬節點越多。
  • 使用SortedDictionary是爲了查找是可以使用二分查找快速找到一個適合的節點。
相關文章
相關標籤/搜索