架构师训练营 week05 作业(hash 算法)
这个算法,hash算法和测试用例,一下子写出来,对我来说比较难,copy一份吧,增强理解
2.4 实现
定义一致性哈希实体。
说明:
定义了函数类型
Hash
,采取依赖注入的方式,允许用户自定义哈希函数,默认为crc32.ChecksumIEEE
算法。Map
是一致性哈希算法的主数据结构,包含 4 个成员变量:Hash 函数hash
;虚拟节点倍数replicas
,即每个真实节点对应replicas
个虚拟节点;哈希环circle
;虚拟节点与真实节点的映射表hashMap
,键是虚拟节点的哈希值,值是真实节点的名称。构造函数
New()
允许自定义虚拟节点倍数和 Hash 函数。
接下来,实现添加真实节点的Add()
方法。
说明:
Add()
方法允许传入0个或多个真实节点的名称。对每个真实节点
peer
,对应创建replicas
个虚拟节点,我们令虚拟节点的名称为strconv.Itoa(i) + peer
,即通过添加编号的方式区分不同虚拟节点。使用
m.hash()
计算虚拟节点的哈希值,使用append(m.circle, hashVal)
把哈希值添加到环上。在
hashMap
中增加虚拟节点和真实节点的映射关系。最后,需要对换上的哈希值进行排序。排序是为了方便后续的查找。
最后,实现选择节点的Get()
方法。
说明:
Get()
方法根据请求的key选择对应的真实节点,返回真实节点的名称。首先,对key计算对应的哈希值。
然后,顺时针找到第一个匹配的虚拟节点的下标
index
。所谓匹配,就是在哈希环m.circle
中,找到第一个哈希值大于等于key的哈希值的虚拟节点。最后,通过
hashMap
映射得到真实的节点。
至此,一致性哈希算法就全部完成了。
2.5 测试
我们测试一致性哈希是否能正常的增加节点和选择节点,另外,我们也测试它在增加节点时数据的迁移率如何,是否针对比传统哈希算法要好。
为了方便说明,这里简化了节点的名称(仅用数字来表示),并且自定义哈希函数。
一开始,有 2/4/6 三个真实节点,对应的虚拟节点的哈希值是 02/12/22、04/14/24、06/16/26。
那么用例 15/11/23/27 选择的虚拟节点分别是 16/12/24/02,也就是真实节点6/2/4/2。
新增一个节点"8",对应增加3个虚拟节点,分别为8,18,28,此时,用例 27 对应的虚拟节点从2变更为 28,即真实节点 8。
测试迁移率
在测试迁移率的函数中,为了保证正确性,我们使用默认的hash函数来计算哈希值(前面的测试是为了方便说明所以自定义了hash函数,在这里就不能这样使用了)。通过执行如下命令,可以看到,相比于传统哈希算法,使用我们自己实现的一致哈希算法可以大大的降低数据迁移率。
评论