zoukankan      html  css  js  c++  java
  • 一致性哈希

    概述:python 实现一致性哈希的功能,然后通过使用功能来了解原理

    我在其他博客中看了很多关于一致性hash的原理,很详细。没有实际的例子,感觉这个理论的应用无从下手。这里我就从实际的例子分析下一致性hash

    先上代码

    import md5
    class HashRing(object):
        def __init__(self, nodes=None, replicas=3):
            """
            nodes: 节点数
            replicas: 虚拟节点个数
            """
            self.replicas = replicas
            self.ring = dict()
            self._sorted_keys = []
            if nodes:
                for node in nodes:
                    self.add_node(node)
        def add_node(self, node):
            """添加一个节点到 hash 环中, 包括所有的虚拟节点"""
            for i in xrange(0, self.replicas):
                key = self.gen_key('%s:%s' % (node, i))
                self.ring[key] = node
                self._sorted_keys.append(key)
            self._sorted_keys.sort()
        def remove_node(self, node):
            """从 hash 环上移除一个节点, 包括所有的虚拟节点一并移除"""
            for i in xrange(0, self.replicas):
                key = self.gen_key('%s:%s' % (node, i))
                del self.ring[key]
                self._sorted_keys.remove(key)
        def get_node(self, string_key):
            """
            根据关键字获取所属节点
            注意: 此处关键字即为需要计算的字符串
            """
            return self.get_node_pos(string_key)[0]
        def get_node_pos(self, string_key):
            """计算虚拟节点"""
            if not self.ring:
                return None, None
            key = self.gen_key(string_key)
            nodes = self._sorted_keys
            for i in xrange(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):
            """Given a string key it returns the nodes as a generator that can hold the key.
            The generator is never ending and iterates through the ring
            starting at the correct position.
            """
            if not self.ring:
                yield None, None
            node, pos = self.get_node_pos(string_key)
            for key in self._sorted_keys[pos:]:
                yield self.ring[key]
            while True:
                for key in self._sorted_keys:
                    yield self.ring[key]
        def gen_key(self, key):
            """Given a string key it returns a long value,
            this long value represents a place on the hash ring.
            md5 is currently used because it mixes well.
            """
            m = md5.new()
            m.update(key)
            return long(m.hexdigest(), 16)
        def print_all(self):
            """打印 hash 环所有节点信息"""
            if not self.ring:
                return None, None
            p = dict()
            for k in list(set(self.ring.values())):
                p[k] = 0
            for i, v in enumerate(self._sorted_keys):
                p[self.ring[v]] += 1
                # print "ring slot %d is node %s, hash vale is %s" % (i, self.ring[i], v)
                print "[{0}] node:{1}#{2} value:{3}".format(i, self.ring[v], p[self.ring[v]], v)
    

    第一步: 创建2个节点的环,每个节点包含3个虚拟节点

     

    上图中前面的 0-5 代表总共有 6 个节点,a#1 表示 a 节点的第一个虚拟节点。图上的value值是按照从小到大的顺序排列,在 hash 环上分布如下图所示

     

    第二步: 计算 key 所属节点,以 ip 举例(字符串类型的都能计算)

     

    上图计算了这三个 ip 所归属的节点,下面具体说明是怎么计算出来的

    首先计算 '192.168.184.1' 的 hash 值,然后从环上找到第一个大于该值的节点返回

    注意:1. 这里是找到的虚拟节点,然后返回的实际节点

               2. 如果没有找到就返回第一个节点

    添加一个节点

    添加的 c 节点,包含了所有的虚拟节点,总共节点数增加了 3

    删除一个节点

    这里将 b 节点删除了, 在 hash 环上所有的虚拟节点都被删除了

    注意:添加节点或者删除节点后,需要将两个节点间的数据重新计算然后分配

  • 相关阅读:
    python 数字格式化
    Python字符串
    Nginx 深入-动静分离, 静态资源css, js 前端请求404问题
    Spring colud gateway 源码小计
    Nginx 场景应用
    Nginx valid_referer 防盗链
    Nginx 基础
    JNI 从零开始一次DEMO调用 IDEA 2018.2.5 + visual studio 2019
    Bitmap 图片说明
    HP激光打印机解密
  • 原文地址:https://www.cnblogs.com/newguy/p/9163032.html
Copyright © 2011-2022 走看看