@@ -11,21 +11,21 @@ type Hash func(data []byte) uint32
11
11
12
12
// Map constains all hashed keys
13
13
type Map struct {
14
- hash Hash
15
- replicas int
16
- keys []int // Sorted
17
- hashMap map [int ]string
14
+ hash Hash // 定义了函数类型 Hash,
15
+ replicas int // 虚拟节点倍数
16
+ keys []int // Sorted 哈希环
17
+ hashMap map [int ]string // 虚拟节点与真实节点的映射表 hashMap,键是虚拟节点的哈希值,值是真实节点的名称。
18
18
}
19
19
20
- // New creates a Map instance
20
+ // New creates a Map instance 构造函数 New() 允许自定义虚拟节点倍数和 Hash 函数。
21
21
func New (replicas int , fn Hash ) * Map {
22
22
m := & Map {
23
23
replicas : replicas ,
24
24
hash : fn ,
25
25
hashMap : make (map [int ]string ),
26
26
}
27
27
if m .hash == nil {
28
- m .hash = crc32 .ChecksumIEEE
28
+ m .hash = crc32 .ChecksumIEEE // 采取依赖注入的方式,允许用于替换成自定义的 Hash 函数,也方便测试时替换,默认为 crc32.ChecksumIEEE 算法。
29
29
}
30
30
return m
31
31
}
@@ -34,11 +34,15 @@ func New(replicas int, fn Hash) *Map {
34
34
func (m * Map ) Add (keys ... string ) {
35
35
for _ , key := range keys {
36
36
for i := 0 ; i < m .replicas ; i ++ {
37
+ // 对每一个真实节点 key,对应创建 m.replicas 个虚拟节点,虚拟节点的名称是:strconv.Itoa(i) + key,即通过添加编号的方式区分不同虚拟节点。
37
38
hash := int (m .hash ([]byte (strconv .Itoa (i ) + key )))
39
+ // 使用 m.hash() 计算虚拟节点的哈希值,使用 append(m.keys, hash) 添加到环上。
38
40
m .keys = append (m .keys , hash )
41
+ // 在 hashMap 中增加虚拟节点和真实节点的映射关系
39
42
m .hashMap [hash ] = key
40
43
}
41
44
}
45
+ // 最后一步,环上的哈希值排序。
42
46
sort .Ints (m .keys )
43
47
}
44
48
@@ -47,12 +51,16 @@ func (m *Map) Get(key string) string {
47
51
if len (m .keys ) == 0 {
48
52
return ""
49
53
}
50
-
54
+ // 第一步,计算 key 的哈希值。
51
55
hash := int (m .hash ([]byte (key )))
52
56
// Binary search for appropriate replica.
57
+ // 第二步,顺时针找到第一个匹配的虚拟节点的下标 idx,从 m.keys 中获取到对应的哈希值。如果 idx == len(m.keys),
58
+ // 说明应选择 m.keys[0],
53
59
idx := sort .Search (len (m .keys ), func (i int ) bool {
60
+ // 寻找到第一个大于这个hash值的keys[i]的坐标idx
54
61
return m .keys [i ] >= hash
55
62
})
56
-
63
+ // 第三步,通过 hashMap 映射得到真实的节点。
64
+ // 因为 m.keys 是一个环状结构,所以用取余数的方式来处理这种情况。
57
65
return m .hashMap [m .keys [idx % len (m .keys )]]
58
66
}
0 commit comments