【week05 作业】
发布于: 2020 年 07 月 06 日
from hashlib import md5from math import sqrt class HashRing(object): def __init__(self, nodes=None, replicas=150): """ 管理hash环 :nodes 节点 :replicas 虚拟节点数 """ self.replicas = replicas self.ring = {} self._sorted_keys = [] if nodes: for node in nodes: self.add_node(node) def add_node(self, node): """ 增加节点 """ for i in range(0, self.replicas): key = self.gen_key(f"{node}:{i}") self.ring[key] = node self._sorted_keys.append(key) self._sorted_keys.sort() def remove_node(self, node): """ 删除节点 """ for i in range(0, self.replicas): key = self.gen_key(f"{node}:{i}") del self.ring[key] self._sorted_keys.remove(key) def get_node_keys(self, node): """ 获取虚拟节点键值 """ keys = [] for i in range(0, self.replicas): key = self.gen_key(f"{node}:{i}") keys.append(key) return keys def get_node(self, string_key): """ 根据键值获取节点 """ return self.get_node_pos(string_key)[0] def get_node_pos(self, string_key): """ 根据传入的键值在hash环上查找节点 """ if not self.ring: return None, None key = self.gen_key(string_key) nodes = self._sorted_keys for i in range(0, len(nodes)): node = nodes[i] if key <= node: return self.ring[node], i return self.ring[nodes[0]], 0 def get_nodes(self, string_key): """ 取得节点列表 """ if not self.ring: yield None node, pos = self.get_node_pos(string_key) for key in self._sorted_keys: yield self.ring[key] def gen_key(self, key): """ 计算hash值 """ m = md5() m.update(key.encode('utf-8')) return int(m.hexdigest(),16)
python语言实现的一致性hash实现。
实现一个hash环类HashRing,构造时根据输入参数确定虚拟节点数。
增加节点是,根据虚拟节点数,生成虚拟节点的hash值并放入hash环。
查找时,根据输入的键值生成hash值,并在hash环上寻找大于此hash值的第一个虚拟节点
测试用例:
#节点数for repl_num in range(100, 410, 10): #服务器数 server_num = 10 #键值数 key_num = 1000000 countTable = {} hr = HashRing(replicas=repl_num) for i in range(0,server_num): server = f"10.1.1.{i+1}" hr.add_node(server) countTable[server] = 0 for i in range(0, key_num): key = f'stringkey{i}' server = hr.get_node(key) countTable[server] = countTable[server] + 1 print(countTable) x = key_num/server_num s2 = 0 for i in range(0,server_num): server = f"10.1.1.{i+1}" s2 = s2 + (countTable[server]-x)*(countTable[server]-x) s = sqrt(s2/server_num) print(f'repls:{repl_num} s:{s}')
输出结果
{'10.1.1.1': 106497, '10.1.1.2': 101200, '10.1.1.3': 104267, '10.1.1.4': 101208, '10.1.1.5': 104813, '10.1.1.6': 94808, '10.1.1.7': 109991, '10.1.1.8': 99603, '10.1.1.9': 87847, '10.1.1.10': 89766}repls:100 s:6825.300359691139{'10.1.1.1': 106355, '10.1.1.2': 98519, '10.1.1.3': 103141, '10.1.1.4': 94973, '10.1.1.5': 111278, '10.1.1.6': 96765, '10.1.1.7': 112456, '10.1.1.8': 93823, '10.1.1.9': 87878, '10.1.1.10': 94812}repls:110 s:7632.430792349184{'10.1.1.1': 94466, '10.1.1.2': 102538, '10.1.1.3': 110266, '10.1.1.4': 102362, '10.1.1.5': 111169, '10.1.1.6': 97092, '10.1.1.7': 111564, '10.1.1.8': 86338, '10.1.1.9': 85035, '10.1.1.10': 99170}repls:120 s:9089.861880138773{'10.1.1.1': 92894, '10.1.1.2': 96431, '10.1.1.3': 114066, '10.1.1.4': 110266, '10.1.1.5': 112072, '10.1.1.6': 95192, '10.1.1.7': 108764, '10.1.1.8': 91157, '10.1.1.9': 82751, '10.1.1.10': 96407}repls:130 s:10003.850018867735{'10.1.1.1': 90858, '10.1.1.2': 92065, '10.1.1.3': 119506, '10.1.1.4': 108892, '10.1.1.5': 112296, '10.1.1.6': 95875, '10.1.1.7': 111127, '10.1.1.8': 89645, '10.1.1.9': 84174, '10.1.1.10': 95562}repls:140 s:11293.7752943823{'10.1.1.1': 92283, '10.1.1.2': 91058, '10.1.1.3': 113011, '10.1.1.4': 110522, '10.1.1.5': 116011, '10.1.1.6': 95122, '10.1.1.7': 112178, '10.1.1.8': 90400, '10.1.1.9': 84424, '10.1.1.10': 94991}repls:150 s:10990.098288914436{'10.1.1.1': 90950, '10.1.1.2': 94887, '10.1.1.3': 108981, '10.1.1.4': 107152, '10.1.1.5': 110638, '10.1.1.6': 95478, '10.1.1.7': 114368, '10.1.1.8': 94463, '10.1.1.9': 86884, '10.1.1.10': 96199}repls:160 s:8927.738302616179{'10.1.1.1': 90550, '10.1.1.2': 98143, '10.1.1.3': 101904, '10.1.1.4': 111191, '10.1.1.5': 106610, '10.1.1.6': 99433, '10.1.1.7': 111487, '10.1.1.8': 95113, '10.1.1.9': 84698, '10.1.1.10': 100871}repls:170 s:8101.678949452391{'10.1.1.1': 87740, '10.1.1.2': 99516, '10.1.1.3': 104017, '10.1.1.4': 111749, '10.1.1.5': 102064, '10.1.1.6': 99504, '10.1.1.7': 113481, '10.1.1.8': 92604, '10.1.1.9': 89092, '10.1.1.10': 100233}repls:180 s:8152.914742593595{'10.1.1.1': 89798, '10.1.1.2': 102824, '10.1.1.3': 106469, '10.1.1.4': 109968, '10.1.1.5': 102730, '10.1.1.6': 97682, '10.1.1.7': 109282, '10.1.1.8': 89975, '10.1.1.9': 91959, '10.1.1.10': 99313}repls:190 s:7196.364276494069{'10.1.1.1': 90230, '10.1.1.2': 102888, '10.1.1.3': 103218, '10.1.1.4': 108327, '10.1.1.5': 106066, '10.1.1.6': 98406, '10.1.1.7': 109300, '10.1.1.8': 89672, '10.1.1.9': 94761, '10.1.1.10': 97132}repls:200 s:6720.529874942898{'10.1.1.1': 88783, '10.1.1.2': 101227, '10.1.1.3': 108627, '10.1.1.4': 108440, '10.1.1.5': 109989, '10.1.1.6': 97889, '10.1.1.7': 107953, '10.1.1.8': 88987, '10.1.1.9': 91711, '10.1.1.10': 96394}repls:210 s:8021.651475849596{'10.1.1.1': 88060, '10.1.1.2': 100883, '10.1.1.3': 112140, '10.1.1.4': 106016, '10.1.1.5': 109863, '10.1.1.6': 95733, '10.1.1.7': 106590, '10.1.1.8': 90449, '10.1.1.9': 93294, '10.1.1.10': 96972}repls:220 s:7944.747472387024{'10.1.1.1': 87107, '10.1.1.2': 101884, '10.1.1.3': 109795, '10.1.1.4': 107034, '10.1.1.5': 111907, '10.1.1.6': 95074, '10.1.1.7': 102667, '10.1.1.8': 92717, '10.1.1.9': 96867, '10.1.1.10': 94948}repls:230 s:7594.297742385401{'10.1.1.1': 88651, '10.1.1.2': 101163, '10.1.1.3': 111115, '10.1.1.4': 107329, '10.1.1.5': 111013, '10.1.1.6': 94798, '10.1.1.7': 102190, '10.1.1.8': 92515, '10.1.1.9': 94313, '10.1.1.10': 96913}repls:240 s:7472.949029666936{'10.1.1.1': 88753, '10.1.1.2': 101837, '10.1.1.3': 111291, '10.1.1.4': 107898, '10.1.1.5': 107261, '10.1.1.6': 94112, '10.1.1.7': 100073, '10.1.1.8': 94151, '10.1.1.9': 95524, '10.1.1.10': 99100}repls:250 s:6798.426538545518{'10.1.1.1': 91360, '10.1.1.2': 101759, '10.1.1.3': 108332, '10.1.1.4': 108535, '10.1.1.5': 106954, '10.1.1.6': 91781, '10.1.1.7': 97927, '10.1.1.8': 97599, '10.1.1.9': 96718, '10.1.1.10': 99035}repls:260 s:5980.694658649612{'10.1.1.1': 94335, '10.1.1.2': 101111, '10.1.1.3': 107718, '10.1.1.4': 108192, '10.1.1.5': 102771, '10.1.1.6': 95312, '10.1.1.7': 97253, '10.1.1.8': 100455, '10.1.1.9': 96858, '10.1.1.10': 95995}repls:270 s:4725.716263171118{'10.1.1.1': 92362, '10.1.1.2': 104268, '10.1.1.3': 110370, '10.1.1.4': 104433, '10.1.1.5': 102467, '10.1.1.6': 99100, '10.1.1.7': 97174, '10.1.1.8': 98333, '10.1.1.9': 96784, '10.1.1.10': 94709}repls:280 s:5096.487496305666{'10.1.1.1': 93287, '10.1.1.2': 102882, '10.1.1.3': 111219, '10.1.1.4': 104439, '10.1.1.5': 98836, '10.1.1.6': 96338, '10.1.1.7': 99413, '10.1.1.8': 102122, '10.1.1.9': 95564, '10.1.1.10': 95900} repls:290 s:5050.164987403877{'10.1.1.1': 94586, '10.1.1.2': 99228, '10.1.1.3': 111053, '10.1.1.4': 104231, '10.1.1.5': 97920, '10.1.1.6': 98168, '10.1.1.7': 100665, '10.1.1.8': 102873, '10.1.1.9': 96447, '10.1.1.10': 94829} repls:300 s:4750.995453586543{'10.1.1.1': 95274, '10.1.1.2': 101512, '10.1.1.3': 111071, '10.1.1.4': 102185, '10.1.1.5': 96639, '10.1.1.6': 99231, '10.1.1.7': 99691, '10.1.1.8': 102446, '10.1.1.9': 98180, '10.1.1.10': 93771} repls:310 s:4604.795391762809{'10.1.1.1': 97880, '10.1.1.2': 104291, '10.1.1.3': 106787, '10.1.1.4': 100839, '10.1.1.5': 96088, '10.1.1.6': 99459, '10.1.1.7': 101433, '10.1.1.8': 100446, '10.1.1.9': 98111, '10.1.1.10': 94666} repls:320 s:3457.5002241503907{'10.1.1.1': 98267, '10.1.1.2': 104615, '10.1.1.3': 107422, '10.1.1.4': 100355, '10.1.1.5': 96200, '10.1.1.6': 99013, '10.1.1.7': 100644, '10.1.1.8': 101803, '10.1.1.9': 97974, '10.1.1.10': 93707} repls:330 s:3772.2653936328497{'10.1.1.1': 99585, '10.1.1.2': 102525, '10.1.1.3': 107589, '10.1.1.4': 99486, '10.1.1.5': 96681, '10.1.1.6': 98887, '10.1.1.7': 101709, '10.1.1.8': 100174, '10.1.1.9': 98145, '10.1.1.10': 95219} repls:340 s:3254.3730579022435{'10.1.1.1': 96699, '10.1.1.2': 102481, '10.1.1.3': 108301, '10.1.1.4': 101180, '10.1.1.5': 99057, '10.1.1.6': 97453, '10.1.1.7': 100970, '10.1.1.8': 99747, '10.1.1.9': 97993, '10.1.1.10': 96119} repls:350 s:3388.547476427031{'10.1.1.1': 96450, '10.1.1.2': 102574, '10.1.1.3': 105087, '10.1.1.4': 102911, '10.1.1.5': 98838, '10.1.1.6': 97023, '10.1.1.7': 100424, '10.1.1.8': 100164, '10.1.1.9': 99243, '10.1.1.10': 97286} repls:360 s:2682.1214737591586{'10.1.1.1': 94082, '10.1.1.2': 103012, '10.1.1.3': 105869, '10.1.1.4': 101738, '10.1.1.5': 98465, '10.1.1.6': 99058, '10.1.1.7': 101929, '10.1.1.8': 96982, '10.1.1.9': 100143, '10.1.1.10': 98722} repls:370 s:3150.9896857971466{'10.1.1.1': 94393, '10.1.1.2': 103231, '10.1.1.3': 106797, '10.1.1.4': 102009, '10.1.1.5': 100109, '10.1.1.6': 99183, '10.1.1.7': 100898, '10.1.1.8': 96818, '10.1.1.9': 97981, '10.1.1.10': 98581} repls:380 s:3313.8183414303203{'10.1.1.1': 94732, '10.1.1.2': 102332, '10.1.1.3': 105133, '10.1.1.4': 101220, '10.1.1.5': 98638, '10.1.1.6': 101655, '10.1.1.7': 103341, '10.1.1.8': 96690, '10.1.1.9': 97637, '10.1.1.10': 98622} repls:390 s:3085.793901089313{'10.1.1.1': 93613, '10.1.1.2': 100909, '10.1.1.3': 104684, '10.1.1.4': 101282, '10.1.1.5': 99522, '10.1.1.6': 101392, '10.1.1.7': 104469, '10.1.1.8': 97123, '10.1.1.9': 98060, '10.1.1.10': 98946} repls:400 s:3170.065993003931
标准差最小的虚拟节点数是360
结果和老师的150到200之间不一样,不知道是否为hash算法不同导致
划线
评论
复制
发布于: 2020 年 07 月 06 日 阅读数: 36
chengjing
关注
程靖 2018.06.06 加入
还未添加个人简介
评论