一致性哈希在分布式系统中被很多的使用,比如说memcached就是使用一致性哈希来做的。学习一下这个一致性哈希算法。
下面这篇博客利用图解的形式,将一致性哈希算法讲述的非常清楚:
博客:http://blog.codinglabs.org/articles/consistent-hashing.html
参考代码,下面我列出了java和c#的两个代码实现,可以通过读代码更深刻的去理解一下这个算法。 代码:
- https://code.google.com/p/consistent-hash/
- https://weblogs.java.net/blog/2007/11/27/consistent-hashing
根据上述文章和代码,仿照着写了一个粗略版本的一致性哈希算法。
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是为了查找是能够使用二分查找快速找到一个适合的节点。