hashring.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. package hashring
  2. import (
  3. "crypto/md5"
  4. "fmt"
  5. "math"
  6. "sort"
  7. )
  8. type HashKey uint32
  9. type HashKeyOrder []HashKey
  10. func (h HashKeyOrder) Len() int { return len(h) }
  11. func (h HashKeyOrder) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
  12. func (h HashKeyOrder) Less(i, j int) bool { return h[i] < h[j] }
  13. type HashRing struct {
  14. ring map[HashKey]string
  15. sortedKeys []HashKey
  16. nodes []string
  17. weights map[string]int
  18. }
  19. func New(nodes []string) *HashRing {
  20. hashRing := &HashRing{
  21. ring: make(map[HashKey]string),
  22. sortedKeys: make([]HashKey, 0),
  23. nodes: nodes,
  24. weights: make(map[string]int),
  25. }
  26. hashRing.generateCircle()
  27. return hashRing
  28. }
  29. func NewWithWeights(weights map[string]int) *HashRing {
  30. nodes := make([]string, 0, len(weights))
  31. for node, _ := range weights {
  32. nodes = append(nodes, node)
  33. }
  34. hashRing := &HashRing{
  35. ring: make(map[HashKey]string),
  36. sortedKeys: make([]HashKey, 0),
  37. nodes: nodes,
  38. weights: weights,
  39. }
  40. hashRing.generateCircle()
  41. return hashRing
  42. }
  43. func (h *HashRing) Size() int {
  44. return len(h.nodes)
  45. }
  46. func (h *HashRing) UpdateWithWeights(weights map[string]int) {
  47. nodesChgFlg := false
  48. if len(weights) != len(h.weights) {
  49. nodesChgFlg = true
  50. } else {
  51. for node, newWeight := range weights {
  52. oldWeight, ok := h.weights[node]
  53. if !ok || oldWeight != newWeight {
  54. nodesChgFlg = true
  55. break
  56. }
  57. }
  58. }
  59. if nodesChgFlg {
  60. newhring := NewWithWeights(weights)
  61. h.weights = newhring.weights
  62. h.nodes = newhring.nodes
  63. h.ring = newhring.ring
  64. h.sortedKeys = newhring.sortedKeys
  65. }
  66. }
  67. func (h *HashRing) generateCircle() {
  68. totalWeight := 0
  69. for _, node := range h.nodes {
  70. if weight, ok := h.weights[node]; ok {
  71. totalWeight += weight
  72. } else {
  73. totalWeight += 1
  74. h.weights[node] = 1
  75. }
  76. }
  77. for _, node := range h.nodes {
  78. weight := h.weights[node]
  79. factor := math.Floor(float64(40*len(h.nodes)*weight) / float64(totalWeight))
  80. for j := 0; j < int(factor); j++ {
  81. nodeKey := fmt.Sprintf("%s-%d", node, j)
  82. bKey := hashDigest(nodeKey)
  83. for i := 0; i < 3; i++ {
  84. key := hashVal(bKey[i*4 : i*4+4])
  85. h.ring[key] = node
  86. h.sortedKeys = append(h.sortedKeys, key)
  87. }
  88. }
  89. }
  90. sort.Sort(HashKeyOrder(h.sortedKeys))
  91. }
  92. func (h *HashRing) GetNode(stringKey string) (node string, ok bool) {
  93. pos, ok := h.GetNodePos(stringKey)
  94. if !ok {
  95. return "", false
  96. }
  97. return h.ring[h.sortedKeys[pos]], true
  98. }
  99. func (h *HashRing) GetNodePos(stringKey string) (pos int, ok bool) {
  100. if len(h.ring) == 0 {
  101. return 0, false
  102. }
  103. key := h.GenKey(stringKey)
  104. nodes := h.sortedKeys
  105. pos = sort.Search(len(nodes), func(i int) bool { return nodes[i] > key })
  106. if pos == len(nodes) {
  107. // Wrap the search, should return first node
  108. return 0, true
  109. } else {
  110. return pos, true
  111. }
  112. }
  113. func (h *HashRing) GenKey(key string) HashKey {
  114. bKey := hashDigest(key)
  115. return hashVal(bKey[0:4])
  116. }
  117. func (h *HashRing) GetNodes(stringKey string, size int) (nodes []string, ok bool) {
  118. pos, ok := h.GetNodePos(stringKey)
  119. if !ok {
  120. return nil, false
  121. }
  122. if size > len(h.nodes) {
  123. return nil, false
  124. }
  125. returnedValues := make(map[string]bool, size)
  126. //mergedSortedKeys := append(h.sortedKeys[pos:], h.sortedKeys[:pos]...)
  127. resultSlice := make([]string, 0, size)
  128. for i := pos; i < pos+len(h.sortedKeys); i++ {
  129. key := h.sortedKeys[i%len(h.sortedKeys)]
  130. val := h.ring[key]
  131. if !returnedValues[val] {
  132. returnedValues[val] = true
  133. resultSlice = append(resultSlice, val)
  134. }
  135. if len(returnedValues) == size {
  136. break
  137. }
  138. }
  139. return resultSlice, len(resultSlice) == size
  140. }
  141. func (h *HashRing) AddNode(node string) *HashRing {
  142. return h.AddWeightedNode(node, 1)
  143. }
  144. func (h *HashRing) AddWeightedNode(node string, weight int) *HashRing {
  145. if weight <= 0 {
  146. return h
  147. }
  148. if _, ok := h.weights[node]; ok {
  149. return h
  150. }
  151. nodes := make([]string, len(h.nodes), len(h.nodes)+1)
  152. copy(nodes, h.nodes)
  153. nodes = append(nodes, node)
  154. weights := make(map[string]int)
  155. for eNode, eWeight := range h.weights {
  156. weights[eNode] = eWeight
  157. }
  158. weights[node] = weight
  159. hashRing := &HashRing{
  160. ring: make(map[HashKey]string),
  161. sortedKeys: make([]HashKey, 0),
  162. nodes: nodes,
  163. weights: weights,
  164. }
  165. hashRing.generateCircle()
  166. return hashRing
  167. }
  168. func (h *HashRing) UpdateWeightedNode(node string, weight int) *HashRing {
  169. if weight <= 0 {
  170. return h
  171. }
  172. /* node is not need to update for node is not existed or weight is not changed */
  173. if oldWeight, ok := h.weights[node]; (!ok) || (ok && oldWeight == weight) {
  174. return h
  175. }
  176. nodes := make([]string, len(h.nodes), len(h.nodes))
  177. copy(nodes, h.nodes)
  178. weights := make(map[string]int)
  179. for eNode, eWeight := range h.weights {
  180. weights[eNode] = eWeight
  181. }
  182. weights[node] = weight
  183. hashRing := &HashRing{
  184. ring: make(map[HashKey]string),
  185. sortedKeys: make([]HashKey, 0),
  186. nodes: nodes,
  187. weights: weights,
  188. }
  189. hashRing.generateCircle()
  190. return hashRing
  191. }
  192. func (h *HashRing) RemoveNode(node string) *HashRing {
  193. /* if node isn't exist in hashring, don't refresh hashring */
  194. if _, ok := h.weights[node]; !ok {
  195. return h
  196. }
  197. nodes := make([]string, 0)
  198. for _, eNode := range h.nodes {
  199. if eNode != node {
  200. nodes = append(nodes, eNode)
  201. }
  202. }
  203. weights := make(map[string]int)
  204. for eNode, eWeight := range h.weights {
  205. if eNode != node {
  206. weights[eNode] = eWeight
  207. }
  208. }
  209. hashRing := &HashRing{
  210. ring: make(map[HashKey]string),
  211. sortedKeys: make([]HashKey, 0),
  212. nodes: nodes,
  213. weights: weights,
  214. }
  215. hashRing.generateCircle()
  216. return hashRing
  217. }
  218. func hashVal(bKey []byte) HashKey {
  219. return ((HashKey(bKey[3]) << 24) |
  220. (HashKey(bKey[2]) << 16) |
  221. (HashKey(bKey[1]) << 8) |
  222. (HashKey(bKey[0])))
  223. }
  224. func hashDigest(key string) [md5.Size]byte {
  225. return md5.Sum([]byte(key))
  226. }