1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374 |
- package utils
- import (
- "fmt"
- "hash/crc32"
- "sort"
- )
- type ConsistentHash struct {
- VirtualNodes int
- virtualNodesMap map[uint32]string
- actNodes map[string]string
- sortRing []uint32
- }
- func NewConsistentHash(virtualNodeNumber int) *ConsistentHash {
- return &ConsistentHash{
- VirtualNodes: virtualNodeNumber,
- virtualNodesMap: make(map[uint32]string),
- actNodes: make(map[string]string),
- sortRing: []uint32{},
- }
- }
- func (c *ConsistentHash) Add(node string) bool {
- if _, ok := c.actNodes[node]; ok {
- return false
- }
- for i := 0; i < c.VirtualNodes; i++ {
- c.virtualNodesMap[c.hashStr(fmt.Sprintf("%s#%d", node, i))] = node
- }
- c.actNodes[node] = node
- c.sortHashRing()
- return true
- }
- func (c *ConsistentHash) sortHashRing() {
- c.sortRing = []uint32{}
- for k := range c.virtualNodesMap {
- c.sortRing = append(c.sortRing, k)
- }
- sort.Slice(c.sortRing, func(i, j int) bool {
- return c.sortRing[i] < c.sortRing[j]
- })
- }
- func (c *ConsistentHash) Get(key string) string {
- hash := c.hashStr(key)
- if len(c.virtualNodesMap) == 0 {
- return ""
- }
- i := c.search(hash)
- return c.virtualNodesMap[c.sortRing[i]]
- }
- func (c *ConsistentHash) hashStr(key string) uint32 {
- return crc32.ChecksumIEEE([]byte(key))
- }
- func (c *ConsistentHash) search(hash uint32) int {
- i := sort.Search(len(c.sortRing), func(i int) bool { return c.sortRing[i] >= hash })
- if i < len(c.sortRing) {
- if i == len(c.sortRing)-1 {
- return 0
- } else {
- return i
- }
- } else {
- return len(c.sortRing) - 1
- }
- }
|