写点什么

架构师训练营 - 第五周作业

用户头像
Mark
关注
发布于: 2021 年 01 月 31 日

问题:


解题:


1. 模拟 master 节点与 server 节点

类型定义

type Master struct {	keys      []int	          //存放虚拟节点的hash值	serverMap map[int]Server  //虚拟节点hash值对应的真实服务器	hasher    hash.Hash32     //hash计算器}
type Server struct { Name string //节点名称 Performance int //性能(生成多少个虚拟节点)}
复制代码


1. 添加 Server 节点

添加节点的思路比较简单,用随机数生成若干虚拟节点,并存储虚拟节点 hash 值与真实节点的映射关系


func (m *Master) Add(servers ...Server) {	rand.Seed(time.Now().Unix())	for _, server := range servers {		for i := 0; i < server.Performance; i++ {			h := rand.Intn(1 << 32)			m.keys = append(m.keys, h)			m.serverMap[h] = server		}	}	sort.Ints(m.keys)}
复制代码


2. 计算给定 key 应存放的节点

寻找节点的思路也比较简单,根据 key 的 hash 值,使用二分查找找到合适的虚节点,并把虚节点对应的真实节点返回即可。


func (m *Master) FindServer(key string) Server {	m.hasher.Write([]byte(key))	h := int(m.hasher.Sum32())	m.hasher.Reset()	l := 0	r := len(m.keys) - 1	for l < r {		i := (l + r) / 2		curr := m.keys[i]		if curr == h {			return m.serverMap[curr]		}		if curr > h {			r = i - 1		} else {			l = i + 1		}	}	i := (l + r) / 2	return m.serverMap[m.keys[i]]}
复制代码


测试结果


第一轮测试为作业要求,测试算法的均衡性

第二轮测试为模拟添加一个较强性能的节点,测试“性能”属性的效果


func main() {	master := Master{		keys:      []int{},		serverMap: make(map[int]Server),		hasher:    crc32.NewIEEE(),	}
//第一轮测试 master.Add( Server{Name: "node1", Performance: 150}, Server{Name: "node2", Performance: 150}, Server{Name: "node3", Performance: 150}, Server{Name: "node4", Performance: 150}, Server{Name: "node5", Performance: 150}, Server{Name: "node6", Performance: 150}, Server{Name: "node7", Performance: 150}, Server{Name: "node8", Performance: 150}, Server{Name: "node9", Performance: 150}, Server{Name: "node10", Performance: 150}) m := make(map[string]int) // 两轮测试使用相同随机数种子,生成一样的测试数据,以排除随机带来的干扰 rand.Seed(100) for i := 0; i < 10000000; i++ { server := master.FindServer(strconv.Itoa(rand.Int())) m[server.Name]++ } fmt.Println(m)
//第二轮测试 master.Add(Server{Name: "node11", Performance: 300}) m = make(map[string]int) rand.Seed(100) for i := 0; i < 10000000; i++ { server := master.FindServer(strconv.Itoa(rand.Int())) m[server.Name]++ } fmt.Println(m)}
复制代码



标准差:

测试 1:

最大值:1202225, 最小值:873655

标准差:107772.07854,


测试 2:

最大值:1198557, 最小值:811913

标准差:106665.37442


测试 3:

最大值:1102031, 最小值:899506

标准差:56236.60706

发布于: 2021 年 01 月 31 日阅读数: 32
用户头像

Mark

关注

还未添加个人签名 2019.06.22 加入

还未添加个人简介

评论

发布
暂无评论
架构师训练营 - 第五周作业