import hashlib # 导入带shal()哈希算法的函数库
class CHash(object):
def __init__(self,nodes=None,v_num=2):# nodes节点存放节点地址,V-num一个节点对应,# 默认节点是为2
self._v_num = v_num # 一个节点对应存放节点地址
self._vNode_IP = {} # 用于虚拟节点的hash值与node的对应关系
self._vNodeAdd = [] # 用于存放所有的虚拟节点的hash值,这里需要保持排序
for node in nodes:
self.addNode(node)
print('\n虚拟节点哈希值升序排列:\n',self._vNodeAdd) # 对虚拟节点哈希地址进行从小到大排序
# 1 建立虚拟节点环,顺序排列
def addNode(self,node):
for i in range(self._v_num):
vNodeStr = '%s%s'%(node ,i) # 根据虚拟节点,为每个节点建立虚拟节点
key = self._gen_key(vNodeStr) # 产生虚拟节点IP地址,服务器节点IP+i
print('虚拟节点字符串',vNodeStr,'对应哈希值',key)
self._vNode_IP[key] = node # 虚拟节点哈希地址为键,节点为IP地址为值
self._vNodeAdd.append(key) # 对应虚拟节点哈希地址进行独立储存
self._vNodeAdd.sort()
# 2 删除退出节点地址及对应的虚拟地址
def Del_Node(self,node): # 删除退出节点地址及对应的虚拟地址
for i in range(self._v_num):
vNodeStr = '%s%s'%(node,i)
key = self._gen_key(vNodeStr) # 产生虚拟节点的哈希地址
del self._vNode_IP[key] # 通过哈希地址删除字典里面的虚拟节点信息
self._vNodeAdd.remove(key) # 删除虚拟节点的哈希地址
# 3 返回数据储存对应的服务器地址
def dataNode(self,data):
if self._vNodeAdd: # 虚拟节点的哈希地址列表不为空
key = self._gen_key(data) # 产生业务数据对应的哈希地址
print(data,'哈希地址',key)
for node_key in self._vNodeAdd: # 获取虚拟节点的哈希地址
if key <= node_key: # 业务数据的哈希地址<= 当前虚拟节点的哈希地址
return self._vNode_IP[node_key] # 返回当前虚拟节点哈希地址对应节点IP
return self._vNodeAdd[self._vNodeAdd[0]] # 如果业务数据的哈希值超过所有节点的地址,则归入并返回第一个IP地址
else:
return None # 没有节点
# 4 通过shal()产生哈希值
@staticmethod # 装饰器
def _gen_key(key_str):
Hash_value = hashlib.sha1(key_str.encode('utf-8')).hexdigest()
return Hash_value
# 测试
C_H = CHash(['192.168.1.1','192.168.1.2','192.168.1.3','192.168.1.4'])
data =['Mike','Margge','Maria']
print('\n正常情况下,存储数据时,归入的节点地址:')
print(data[0]+'存入的节点IP地址:',C_H.dataNode(data[0]))
print(data[1]+'存入的节点IP地址:',C_H.dataNode(data[1]))
print(data[2]+'存入的节点IP地址:',C_H.dataNode(data[2]))
# 192.168.2.1删除节点
print('\n192.168.1.2节点脱离分布式系统的情况:')
C_H.Del_Node('192.168.1.2') # 删除节点
print(data[0]+'存入的节点IP地址:',C_H.dataNode(data[0]))
print(data[1]+'存入的节点IP地址:',C_H.dataNode(data[1]))
print(data[2]+'存入的节点IP地址:',C_H.dataNode(data[2]))
|