概述: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 print p 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个虚拟节点