Go实现一致性哈希

用Golang实现简单场景的一致性哈希

Posted by Daniel on April 20, 2016

Golang的一致性哈希实现

一致性哈希的具体介绍,可以参考: http://www.cnblogs.com/haippy/archive/2011/12/10/2282943.html

import (
    "hash/crc32"
    "sort"
    "strconv"
    "sync"
)

const DEFAULT_REPLICAS = 100
type SortKeys []uint32

func (sk SortKeys) Len() int {
    return len(sk)
}

func (sk SortKeys) Less(i, j int) bool {
    return sk[i] < sk[j]
}

func (sk SortKeys) Swap(i, j int) {
    sk[i], sk[j] = sk[j], sk[i]
}

type HashRing struct {
    Nodes map[uint32]string
    Keys  SortKeys
    sync.RWMutex
}

func (hr *HashRing)New(nodes []string) {
    if nodes == nil {
        return
    }

    hr.Nodes = make(map[uint32]string)
    hr.Keys = SortKeys{}
    for _, node := range(nodes) {
        for i := 0; i < DEFAULT_REPLICAS; i++ {
            str := node + strconv.Itoa(i)
            hr.Nodes[hr.hashStr(str)] = node
            hr.Keys = append(hr.Keys, hr.hashStr(str))
        }
    }
    sort.Sort(hr.Keys)
}

func (hr *HashRing) hashStr(key string) uint32 {
    return crc32.ChecksumIEEE([]byte(key))
}

func (hr *HashRing) GetNode(key string) string {
    hr.RLock()
    defer hr.RUnlock()
    hash := hr.hashStr(key)
    i := hr.get_position(hash)
    return hr.Nodes[hr.Keys[i]]
}

func (hr *HashRing) get_position(hash uint32) int {
    i := sort.Search(len(hr.Keys), func(i int) bool {
        return hr.Keys[i] >= hash})

    if i < len(hr.Keys) {
        if i == len(hr.Keys) - 1 {
            return 0
        } else {
            return i
        }
    } else {
        return len(hr.Keys) - 1
    }
}