-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhashring.go
108 lines (91 loc) · 2.02 KB
/
hashring.go
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package algorithm
import (
"hash"
"hash/crc32"
"sort"
"strconv"
"sync"
)
type node struct {
nodeKey string
nodeV uint32
}
type nodes []*node
func (a nodes) Len() int { return len(a) }
func (a nodes) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a nodes) Less(i, j int) bool { return a[i].nodeV < a[j].nodeV }
var defaultVirtualNodes int = 1000
// HashRing 一致性hash环
type HashRing struct {
virtualNodes int
weight map[string]int
nodesList nodes
mu sync.Mutex
}
// NewHashRing new方法
func NewHashRing(virtual int) *HashRing {
if virtual == 0 {
virtual = defaultVirtualNodes
}
hr := &HashRing{
virtualNodes: virtual,
weight: make(map[string]int),
}
hr.genarate()
return hr
}
// Update 更新
func (hr *HashRing) Update(name string, weight int) {
hr.mu.Lock()
defer hr.mu.Unlock()
hr.weight[name] = weight
hr.genarate()
}
// Delete 删除节点
func (hr *HashRing) Delete(name string) {
hr.mu.Lock()
defer hr.mu.Unlock()
delete(hr.weight, name)
hr.genarate()
}
// Add 添加节点
func (hr *HashRing) Add(name string, weight int) {
hr.Update(name, weight)
}
// GetNode 查找对应的节点key
func (hr *HashRing) GetNode(key string) string {
hr.mu.Lock()
defer hr.mu.Unlock()
hashValue := hashValue(key)
n := sort.Search(hr.nodesList.Len(), func(i int) bool {
return hashValue <= hr.nodesList[i].nodeV
})
if n >= hr.nodesList.Len() && n < 0 {
n = 0
}
return hr.nodesList[n].nodeKey
}
func (hr *HashRing) genarate() {
allWeight := 0
for _, w := range hr.weight {
allWeight += w
}
for key, w := range hr.weight {
var allocNodes int = int(float32(w) / float32(allWeight) * float32(hr.virtualNodes))
for i := 0; i < allocNodes; i++ {
vNode := &node{
nodeKey: key,
nodeV: hashValue(key + ":" + strconv.Itoa(i)),
}
hr.nodesList = append(hr.nodesList, vNode)
}
}
sort.Sort(hr.nodesList)
}
var hs hash.Hash32 = crc32.NewIEEE()
func hashValue(key string) uint32 {
hs.Write([]byte(key))
value := hs.Sum32()
hs.Reset()
return value
}