import hashlib
import random
import numpy as np
# 获取到经过MD5加密的字符串并返回
def md5_encode(str):
str = str.encode('utf-8')
m = hashlib.md5()
m.update(str)
return m.hexdigest()
class NodeInfo(object):
def __init__(self, hash_key, node, virtual_node):
self.hash_key = hash_key
self.node = node
self.virtual_node = virtual_node
class ConsistencyHash(object):
def __init__(self):
self.nodes = []
self.key_nodes = []
# 每个节点虚拟出多少节点
self.virtual_node_num = 185
@staticmethod
def get_hash_key(key):
md5 = md5_encode(key)
# 将md5值当成16进制解析,转成10进制,除进2的32次方,计算hash值
return int(md5, 16) % (2 ** 32)
# 获取某个key值对应的node
def get_node(self, str):
hash_key = self.get_hash_key(str)
for i, val in enumerate(self.key_nodes):
if hash_key < val.hash_key:
return val.node
return self.key_nodes[-1].node
# 添加服务器
def add_node(self, node):
self.nodes.append(node)
for num in range(0, self.virtual_node_num):
virtual_node = node + '#' + str(num)
virtual_node_key = self.get_hash_key(virtual_node)
node_info = NodeInfo(virtual_node_key, node, virtual_node)
self.key_nodes.append(node_info)
# 按hash key 从小到大排序
self.key_nodes.sort(key=lambda n: n.hash_key)
# 生成随机字符串
def random_str(slen=10):
seed = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()_+=-"
sa = []
for i in range(slen):
sa.append(random.choice(seed))
return ''.join(sa)
if __name__ == '__main__':
consistency_hash = ConsistencyHash()
nodes = [
"192.168.1.1",
"192.168.1.2",
"192.168.1.3",
"192.168.1.4",
"192.168.1.5",
"192.168.1.6",
"192.168.1.7",
"192.168.1.8",
"192.168.1.9",
"192.168.1.10",
]
map_node_count = {}
for node in nodes:
consistency_hash.add_node(node)
map_node_count[node] = 0
for i in range(0, 1000000):
slen = random.randint(1, 50)
str = random_str(slen)
node = consistency_hash.get_node(str)
map_node_count[node] += 1
print(map_node_count)
print(np.std(list(map_node_count.values()), ddof=1))
评论