# -*- coding: utf-8 -*- """ 一致性哈希算法 python实现 参考 http://weblogs.java.net/blog/2007/11/27/consistent-hashing http://code.google.com/p/flexihash/ http://www.codinglabs.org/html/consistent-hashing.html """ import hashlib class ConsistentHash(object): def __init__(self, hasher=None, replicas=None): self.hasher = hasher and hasher or hashlib.md5 self.replicas = replicas and replicas or 64 self.positionToTarget = {} self.targetToPositions = {} self.targetCount = 0 def addTarget(self, target): self.targetToPositions[target] = [] for i in range(self.replicas): position = self.hasher(str(target)+str(i)).hexdigest() self.positionToTarget[position] = target self.targetToPositions[target].append(position) self.targetCount += 1 def addTargets(self, targets): for target in targets: self.addTarget(target) def removeTarget(self, target): if self.targetToPositions.has_key(target): for position in self.targetToPositions[target]: self.positionToTarget.pop(position) self.targetToPositions.pop(target) self.targetCount -= 1 def getAllTargets(self): return self.targetToPositions.keys() def lookupList(self, resource, requestedCount): if not self.positionToTarget: return [] resourcePosition = self.hasher(resource).hexdigest() results = [] collect = False for key in sorted(self.positionToTarget.keys()): value = self.positionToTarget[key] if not collect and key > resourcePosition: collect = True if collect and value not in results: results.append(value) if len(results) == requestedCount or \ len(results) == self.targetCount: return results for key in sorted(self.positionToTarget.keys()): value = self.positionToTarget[key] if value not in results: results.append(value) if len(results) == requestedCount or \ len(results) == self.targetCount: return results return results def lookup(self, resource): targets = self.lookupList(resource, 1) return targets[0]