架构师训练营 -W05H- 技术选型
发布于: 2020 年 07 月 08 日
一、用你熟悉的编程语言实现一致性 hash 算法。二、编写测试用例测试这个算法,测试 100 万 KV 数据,10 个服务器节点的情况下,计算这些 KV 数据在服务器上分布数量的标准差,以评估算法的存储负载不均衡性。
0 综述
一致性哈希算法可以解决取模哈希算法存在的节点扩容、节点宕机所带来的问题。而在一致性哈希中引入虚拟节点则可以进一步解决一致性哈希数据分布不均所带来的平衡性问题。
1 代码
# -*- coding: utf-8 -*-import hashlib, random, stringimport numpy as npcontent_list = []# 随机生成1000000个四位字符串用于模拟key值进行测试for i in range(10**7): ran_str = ''.join(random.sample(string.ascii_letters + string.digits, 4)) content_list.append(ran_str)# 设置10个服务器节点servers = [ "10.10.1.1", "10.10.2.2", "10.10.3.3", "10.10.4.4", "10.10.5.5", "10.10.6.6", "10.10.7.7", "10.10.8.8", "10.10.9.9", "10.10.10.10",]class HashRing: def __init__(self, nodes=None, replicas=3): self.replicas = replicas self.ring = dict() self._sorted_keys = [] if nodes: for node in nodes: self.add_node(node) def add_node(self, node): """ Adds a `node` to the hash ring (including a number of replicas) """ for i in range(self.replicas): virtual_node = f"{node}#{i}" key = self.gen_key(virtual_node) self.ring[key] = node self._sorted_keys.append(key) # print(f"{virtual_node} --> {key} --> {node}") self._sorted_keys.sort() # print([self.ring[key] for key in self._sorted_keys]) def remove_node(self, node): """ Removes `node` from the hash ring and its replicas """ for i in range(self.replicas): key = self.gen_key(f"{node}#{i}") del self.ring[key] self._sorted_keys.remove(key) def get_node(self, string_key): """ Given a string key a corresponding node in the hash ring is returned. If the hash ring is empty, `None` is returned. """ return self.get_node_pos(string_key)[0] def get_node_pos(self, string_key): """ Given a string key a corresponding node in the hash ring is returned along with it's position in the ring. If the hash ring is empty, (`None`, `None`) is returned. """ if not self.ring: return None, None key = self.gen_key(string_key) nodes = self._sorted_keys for i in range(len(nodes)): node = nodes[i] if key < node: return self.ring[node], i # 如果key > node,那么让这些key落在第一个node上就形成了闭环 return self.ring[nodes[0]], 0 def gen_key(self, string_key): """ Given a string key it returns a long value, this long value represents a place on the hash ring """ m = hashlib.md5() m.update(string_key.encode('utf-8')) return m.hexdigest()def consistent_hash(replicas): hr = HashRing(servers, replicas) database = {s: [] for s in servers} for w in content_list: database[hr.get_node(w)].append(w) # print(f"words={len(words)}\n") arr = [] # 输出每个节点分配的数量 for node, result in database.items(): print(f"{node}={len(result)}") arr.append(len(result)) # 输出标准差 print("标准差为:"+str(np.std(arr)))if __name__ == '__main__': consistent_hash(100)
2 虚拟节点数量取值为10
虚拟节点数量取值为10
if __name__ == '__main__': consistent_hash(10)
各个节点分布数量及方差为:
10.10.1.1=77875410.10.2.2=125224610.10.3.3=77996410.10.4.4=85995310.10.5.5=49771010.10.6.6=116951910.10.7.7=118356910.10.8.8=93459510.10.9.9=190337910.10.10.10=640311标准差为:400705.483719513
3 虚拟节点数量取值为50
虚拟节点数量取值为50
if __name__ == '__main__': consistent_hash(50)
各个节点分布数量及方差为:
10.10.1.1=107922110.10.2.2=88762110.10.3.3=88671410.10.4.4=116382810.10.5.5=96558210.10.6.6=90565710.10.7.7=92640710.10.8.8=110361010.10.9.9=91621410.10.10.10=1165146标准差为:109136.51776376228
4 虚拟节点数量取值为100
虚拟节点数量为100
if __name__ == '__main__': consistent_hash(100)
各个节点分布数量及方差为:
10.10.1.1=84961110.10.2.2=100179210.10.3.3=107086210.10.4.4=104548810.10.5.5=96045510.10.6.6=101952410.10.7.7=108486910.10.8.8=107995010.10.9.9=92549610.10.10.10=961953标准差为:72283.33643378672
5 虚拟节点数量取值为150
虚拟节点数量为150
if __name__ == '__main__': consistent_hash(150)
各个节点分布数量及方差为:
10.10.1.1=102158010.10.2.2=97908110.10.3.3=105109610.10.4.4=106836410.10.5.5=87912010.10.6.6=102005510.10.7.7=105337910.10.8.8=92685910.10.9.9=102371110.10.10.10=976755标准差为:57011.73665658677
6 虚拟节点数量取值为200
虚拟节点数量为150
if __name__ == '__main__': consistent_hash(200)
各个节点分布数量及方差为:
10.10.1.1=104936110.10.2.2=101619410.10.3.3=109130710.10.4.4=104716210.10.5.5=99977810.10.6.6=93699010.10.7.7=91532410.10.8.8=100324010.10.9.9=96613210.10.10.10=974512标准差为:51193.249533507835
7 结论
随着虚拟节点数量的不断增加,标准方差逐渐递减,且虚拟节点取到150和200的时候标准方差基本相同。
8 参考
https://reishin.me/python-consistent-hash/#取模-hash
划线
评论
复制
发布于: 2020 年 07 月 08 日 阅读数: 34
BlazeLuLu
关注
还未添加个人签名 2018.05.30 加入
还未添加个人简介
评论