feat(transport): add hash transport

This commit is contained in:
bandl 2021-10-24 19:12:07 +08:00
parent ebfa948421
commit e81124c7e6
2 changed files with 92 additions and 0 deletions

View File

@ -0,0 +1,7 @@
package transport
type TransPortInterface interface {
GetTargetAddr(...string) (string, error)
IsEmpty() bool
AddTarget(targets ...string)
}

85
gateway/transport/hash.go Normal file
View File

@ -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
}