[python]python3一致性hash

算法很简单,代码根据网上改的

移植到python3

不过量少场景, 一致性hash不均匀的问题很难解决,加虚拟节点也不是很管用

# -*- coding: utf-8 -*-
import hashlib
 
class ConHash(object):
    def __init__(self, nodes=None, n_number=16):
        """
        :param nodes:           所有的节点
        :param n_number:        一个节点对应多少个虚拟节点
        :return:
        """
        self._n_number = n_number   #每一个节点对应多少个虚拟节点,这里默认是3个
        self._node_dict = dict()    #用于将虚拟节点的hash值与node的对应关系
        self._sort_list = []        #用于存放所有的虚拟节点的hash值,这里需要保持排序
        if nodes:
            for node in nodes:
                self.add_node(node)
 
    def add_node(self, node):
        """
        添加node,首先要根据虚拟节点的数目,创建所有的虚拟节点,并将其与对应的node对应起来
        当然还需要将虚拟节点的hash值放到排序的里面
        这里在添加了节点之后,需要保持虚拟节点hash值的顺序
        :param node:
        :return:
        """
        for i in range(self._n_number):
            node_str = "%s#%s" % (node,i)    #虚拟节点=n#真实节点#n
            key = self._gen_key(node_str)     #计算虚拟节点的key
            self._node_dict[key] = node       #key和真实节点的对应关系
            self._sort_list.append(key)
        self._sort_list.sort()
 
    def remove_node(self, node):
        """
        这里一个节点的退出,需要将这个节点的所有的虚拟节点都删除
        :param node:
        :return:
        """
        for i in range(self._n_number):
            node_str = "%s#%s" % (node, i)
            key = self._gen_key(node_str)
            del self._node_dict[key]
            self._sort_list.remove(key)
 
    def get_node(self, key_str):
        """
        返回这个字符串应该对应的node,这里先求出字符串的hash值,然后找到第一个小于等于的虚拟节点,然后返回node
        如果hash值大于所有的节点,那么用第一个虚拟节点
        :param :
        :return:
        """
        if self._sort_list:
            key = self._gen_key(key_str)
            for node_key in self._sort_list:
                if key <= node_key:
                    return self._node_dict[node_key]
            return self._node_dict[self._sort_list[0]]
        else:
            return None
 
    @staticmethod
    def _gen_key(key_str):
        """
        通过key,返回当前key的hash值,这里采用md5
        :param key:
        :return:
        """
        md5_str = hashlib.md5(key_str.encode(encoding='UTF-8')).hexdigest()   #16进制
        #return long(md5_str, 16)  #p3 不支持long
        #print(int(md5_str,16),md5_str)
        #return int(md5_str,16)
        return md5_str   #用hexdigest当key也没问题
 
 
ring = ConHash(["192.168.1.1","192.168.1.2","192.168.1.3","192.168.1.4"])
print(ring.get_node("DV001"))
print(ring.get_node("DV002"))
print(ring.get_node("DV003"))
print(ring.get_node("DV004"))
print(ring.get_node("DV005"))
print(ring.get_node("DV006"))
print(ring.get_node("DV007"))
print(ring.get_node("DV008"))
print(ring.get_node("DV009"))
print(ring.get_node("DV010"))
print(ring.get_node("DV011"))
print(ring.get_node("DV012"))
print(ring.get_node("DV013"))
print(ring.get_node("DV014"))
print(ring.get_node("DV015"))
print(ring.get_node("DV016"))
'''
 测试结果很不均匀。。。。
 (vgflask64) d:\fk\work\python\vgflask64\work\test>python tchash.py
192.168.1.2
192.168.1.2
192.168.1.1
192.168.1.3
192.168.1.2
192.168.1.1
192.168.1.3
192.168.1.1
192.168.1.3
192.168.1.3
192.168.1.1
192.168.1.3
'''

 

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值