forked from p93542168/wheat-cache
feat(transport): add hash transport
This commit is contained in:
parent
ebfa948421
commit
e81124c7e6
|
@ -0,0 +1,7 @@
|
||||||
|
package transport
|
||||||
|
|
||||||
|
type TransPortInterface interface {
|
||||||
|
GetTargetAddr(...string) (string, error)
|
||||||
|
IsEmpty() bool
|
||||||
|
AddTarget(targets ...string)
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
package transport
|
||||||
|
|
||||||
|
import (
|
||||||
|
"hash/crc32"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"gitee.com/timedb/wheatCache/pkg/errorx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HashFunc func(data []byte) uint32
|
||||||
|
|
||||||
|
// 实现 sort
|
||||||
|
type UInt32Slice []uint32
|
||||||
|
|
||||||
|
func (s UInt32Slice) Len() int {
|
||||||
|
return len(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s UInt32Slice) Less(i, j int) bool {
|
||||||
|
return s[i] < s[j]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s UInt32Slice) Swap(i, j int) {
|
||||||
|
s[i], s[j] = s[j], s[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
type HashTransport struct {
|
||||||
|
hash HashFunc
|
||||||
|
replicas int // 复制因子
|
||||||
|
keys UInt32Slice
|
||||||
|
hashMap map[uint32]string // taraget 隐射
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHashTransport(replicas int, fn HashFunc, target ...string) TransPortInterface {
|
||||||
|
transport := &HashTransport{
|
||||||
|
replicas: replicas,
|
||||||
|
hash: fn,
|
||||||
|
hashMap: make(map[uint32]string, len(target)),
|
||||||
|
}
|
||||||
|
|
||||||
|
if transport.hash == nil {
|
||||||
|
transport.hash = crc32.ChecksumIEEE // 默认使用 CRC32 算法
|
||||||
|
}
|
||||||
|
|
||||||
|
transport.AddTarget(target...)
|
||||||
|
|
||||||
|
return transport
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HashTransport) IsEmpty() bool {
|
||||||
|
return len(h.keys) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HashTransport) AddTarget(targets ...string) {
|
||||||
|
for _, tar := range targets {
|
||||||
|
|
||||||
|
for i := 0; i < h.replicas; i++ {
|
||||||
|
hash := h.hash([]byte(strconv.Itoa(i) + tar))
|
||||||
|
h.keys = append(h.keys, hash)
|
||||||
|
h.hashMap[hash] = tar
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 虚拟值排序,方便查找
|
||||||
|
sort.Sort(h.keys)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HashTransport) GetTargetAddr(str ...string) (string, error) {
|
||||||
|
if h.IsEmpty() {
|
||||||
|
return "", errorx.New("gateway not register transport")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(str) != 1 {
|
||||||
|
return "", errorx.New("must give key")
|
||||||
|
|
||||||
|
}
|
||||||
|
hash := h.hash([]byte(str[0]))
|
||||||
|
idx := sort.Search(len(h.keys), func(i int) bool { return h.keys[i] >= hash })
|
||||||
|
if idx == len(h.keys) {
|
||||||
|
return h.hashMap[h.keys[0]], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return h.hashMap[h.keys[idx]], nil
|
||||||
|
}
|
Loading…
Reference in New Issue