@@ -11,21 +11,21 @@ type Hash func(data []byte) uint32
1111
1212// Map constains all hashed keys
1313type 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,键是虚拟节点的哈希值,值是真实节点的名称。
1818}
1919
20- // New creates a Map instance
20+ // New creates a Map instance 构造函数 New() 允许自定义虚拟节点倍数和 Hash 函数。
2121func New (replicas int , fn Hash ) * Map {
2222 m := & Map {
2323 replicas : replicas ,
2424 hash : fn ,
2525 hashMap : make (map [int ]string ),
2626 }
2727 if m .hash == nil {
28- m .hash = crc32 .ChecksumIEEE
28+ m .hash = crc32 .ChecksumIEEE // 采取依赖注入的方式,允许用于替换成自定义的 Hash 函数,也方便测试时替换,默认为 crc32.ChecksumIEEE 算法。
2929 }
3030 return m
3131}
@@ -34,11 +34,15 @@ func New(replicas int, fn Hash) *Map {
3434func (m * Map ) Add (keys ... string ) {
3535 for _ , key := range keys {
3636 for i := 0 ; i < m .replicas ; i ++ {
37+ // 对每一个真实节点 key,对应创建 m.replicas 个虚拟节点,虚拟节点的名称是:strconv.Itoa(i) + key,即通过添加编号的方式区分不同虚拟节点。
3738 hash := int (m .hash ([]byte (strconv .Itoa (i ) + key )))
39+ // 使用 m.hash() 计算虚拟节点的哈希值,使用 append(m.keys, hash) 添加到环上。
3840 m .keys = append (m .keys , hash )
41+ // 在 hashMap 中增加虚拟节点和真实节点的映射关系
3942 m .hashMap [hash ] = key
4043 }
4144 }
45+ // 最后一步,环上的哈希值排序。
4246 sort .Ints (m .keys )
4347}
4448
@@ -47,12 +51,16 @@ func (m *Map) Get(key string) string {
4751 if len (m .keys ) == 0 {
4852 return ""
4953 }
50-
54+ // 第一步,计算 key 的哈希值。
5155 hash := int (m .hash ([]byte (key )))
5256 // Binary search for appropriate replica.
57+ // 第二步,顺时针找到第一个匹配的虚拟节点的下标 idx,从 m.keys 中获取到对应的哈希值。如果 idx == len(m.keys),
58+ // 说明应选择 m.keys[0],
5359 idx := sort .Search (len (m .keys ), func (i int ) bool {
60+ // 寻找到第一个大于这个hash值的keys[i]的坐标idx
5461 return m .keys [i ] >= hash
5562 })
56-
63+ // 第三步,通过 hashMap 映射得到真实的节点。
64+ // 因为 m.keys 是一个环状结构,所以用取余数的方式来处理这种情况。
5765 return m .hashMap [m .keys [idx % len (m .keys )]]
5866}
0 commit comments