架构师训练营 1 期 -- 第五周作业
发布于: 2020 年 10 月 22 日
用你熟悉的编程语言实现一致性 hash 算法。
答:使用Python实现,开发环境,windows 10,python 3.8,pytest 6.1.1。代码如下:
import mathimport bisectfrom abc import ABCclass ConsistentHashRing(ABC): """ 普通一致性Hash环,存储键值对,key是hash值,value是node IP或名称 """ def __init__(self, nodes=[]): """ 对传入的节点构建hash环 :param nodes: """ self.nodes = nodes # 节点的hash code数组 self.node_array = [] # 节点hash code和节点信息的mapping self.node_dict = {} self.ring_len = pow(2, 16) - 1 # 创建节点 for node in self.nodes: hash_code = self.get_hash_code(node) self.add_node(hash_code, node) pass def add_node(self, hash_code, node): """ 将节点有序添加到hash_code的位置 :param hash_code: :param node: :return: """ bisect.insort(self.node_array, hash_code) self.node_dict[hash_code] = node pass def get_node(self, key): """ 根据key的hash值获取距离最近的节点信息 :param key: :return: """ hash_code = self.get_hash_code(key) for node in self.node_array: if hash_code <= node: return self.node_dict[node] return self.node_dict[self.node_array[0]] def get_hash_code(self, key): """ 计算hash code :param key: :return: """ return math.fabs(hash(key)) % self.ring_lenclass AdvancedHashRing(ConsistentHashRing): """ 使用虚拟节点构建一致性hash环 """ def __init__(self, nodes, replicas): """ 构造函数,对每个节点创建replicas个虚拟节点,平均分配到hash环上。 :param nodes: 节点列表 :param replicas: 每隔节点创建的虚拟节点数目 """ super().__init__() self.nodes = nodes self.replicas = replicas self.generate_virtual_node() def generate_virtual_node(self): for node in self.nodes: for i in range(self.replicas): # 创建虚拟节点 hash_code = self.get_hash_code(node + str(i)) self.add_node(hash_code, node)
编写测试用例测试这个算法,测试 100 万 KV 数据,10 个服务器节点的情况下,计算这些 KV 数据在服务器上分布数量的标准差,以评估算法的存储负载不均衡性。
答:测试代码如下:
# -*- coding:utf-8 -*-import mathimport pytestfrom consistent_hash_ring import AdvancedHashRing@pytest.fixturedef input_data(): node_list = ['node' + str(i) for i in range(10)] key_list = ('key' + str(j) for j in range(1000000)) return node_list, key_list@pytest.mark.parametrize('replicas', [10, 50, 100, 150, 200, 300, 500])def test_hash_ring(input_data, replicas): ring = AdvancedHashRing(input_data[0], replicas) result = {} for key in input_data[1]: node = ring.get_node(key) if node in result: result[node] = result[node] + 1 else: result[node] = 1 print('使用 {} 个虚拟节点,测试结果如下:'.format(replicas)) print(result) print('方差: {}'.format(calculate_standard_deviation(result, 100000))) print('**************************************') print()def calculate_standard_deviation(result, average): my_sum = 0 for item in result.values(): my_sum = my_sum + math.pow(item - average, 2) return int(math.sqrt(my_sum / len(result)))# 如果未安装pytest,使用如下代码测试# test_hash_ring(input_data(), 10)# test_hash_ring(input_data(), 100)# test_hash_ring(input_data(), 150)# test_hash_ring(input_data(), 300)# test_hash_ring(input_data(), 1000)
使用pytest测试,得到测试结果如下:
划线
评论
复制
发布于: 2020 年 10 月 22 日阅读数: 53
曾彪彪
关注
还未添加个人签名 2019.03.23 加入
还未添加个人简介
评论