hash_ring

# -*- coding: utf-8 -*-
"""
hash_ring
~~~~~~~~~~~~~~
Implements consistent hashing that can be used when
the number of server nodes can increase or decrease (like in memcached). Consistent hashing is a scheme that provides a hash table functionality
in a way that the adding or removing of one slot
does not significantly change the mapping of keys to slots. More information about consistent hashing can be read in these articles: "Web Caching with Consistent Hashing":
http://www8.org/w8-papers/2a-webserver/caching/paper2.html "Consistent hashing and random trees:
Distributed caching protocols for relieving hot spots on the World Wide Web (1997)":
http://citeseerx.ist.psu.edu/legacymapper?did=38148 Example of usage:: memcache_servers = ['192.168.0.246:11212',
'192.168.0.247:11212',
'192.168.0.249:11212'] ring = HashRing(memcache_servers)
server = ring.get_node('my_key') :copyright: 2008 by Amir Salihefendic.
:license: BSD
""" import math
import sys
from bisect import bisect if sys.version_info >= (2, 5):
import hashlib
md5_constructor = hashlib.md5
else:
import md5
md5_constructor = md5.new class HashRing(object): def __init__(self, nodes=None, weights=None):
"""`nodes` is a list of objects that have a proper __str__ representation.
`weights` is dictionary that sets weights to the nodes. The default
weight is that all nodes are equal.
"""
self.ring = dict()
self._sorted_keys = [] self.nodes = nodes if not weights:
weights = {}
self.weights = weights self._generate_circle() def _generate_circle(self):
"""Generates the circle.
"""
total_weight = 0
for node in self.nodes:
total_weight += self.weights.get(node, 1) for node in self.nodes:
weight = 1 if node in self.weights:
weight = self.weights.get(node) factor = math.floor((40*len(self.nodes)*weight) / total_weight); for j in range(0, int(factor)):
b_key = self._hash_digest( '%s-%s' % (node, j) ) for i in range(0, 3):
key = self._hash_val(b_key, lambda x: x+i*4)
self.ring[key] = node
self._sorted_keys.append(key) self._sorted_keys.sort() def get_node(self, string_key):
"""Given a string key a corresponding node in the hash ring is returned. If the hash ring is empty, `None` is returned.
"""
pos = self.get_node_pos(string_key)
if pos is None:
return None
return self.ring[ self._sorted_keys[pos] ] def get_node_pos(self, string_key):
"""Given a string key a corresponding node in the hash ring is returned
along with it's position in the ring. If the hash ring is empty, (`None`, `None`) is returned.
"""
if not self.ring:
return None key = self.gen_key(string_key) nodes = self._sorted_keys
pos = bisect(nodes, key) if pos == len(nodes):
return 0
else:
return pos def iterate_nodes(self, string_key, distinct=True):
"""Given a string key it returns the nodes as a generator that can hold the key. The generator iterates one time through the ring
starting at the correct position. if `distinct` is set, then the nodes returned will be unique,
i.e. no virtual copies will be returned.
"""
if not self.ring:
yield None, None returned_values = set()
def distinct_filter(value):
if str(value) not in returned_values:
returned_values.add(str(value))
return value pos = self.get_node_pos(string_key)
for key in self._sorted_keys[pos:]:
val = distinct_filter(self.ring[key])
if val:
yield val for i, key in enumerate(self._sorted_keys):
if i < pos:
val = distinct_filter(self.ring[key])
if val:
yield val 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.
"""
b_key = self._hash_digest(key)
return self._hash_val(b_key, lambda x: x) def _hash_val(self, b_key, entry_fn):
return (( b_key[entry_fn(3)] << 24)
|(b_key[entry_fn(2)] << 16)
|(b_key[entry_fn(1)] << 8)
| b_key[entry_fn(0)] ) def _hash_digest(self, key):
m = md5_constructor()
m.update(bytes(key,encoding='utf-8'))
#return map(ord, m.digest())
return list(m.digest()) '''
memcache_servers = ['192.168.0.246:11212',
'192.168.0.247:11212',
'192.168.0.249:11212'] ring = HashRing(memcache_servers)
server = ring.get_node('my_key')
''' # 增加权重 memcache_servers = ['192.168.0.246:11212',
'192.168.0.247:11212',
'192.168.0.249:11212']
weights = {
'192.168.0.246:11212': 1,
'192.168.0.247:11212': 2,
'192.168.0.249:11212': 1
} ring = HashRing(memcache_servers, weights)
server = ring.get_node('my_key')
print(server)

增加删除机器时有可能数据找不到

python 一致性哈希 分布式的更多相关文章

  1. php实现一致性哈希算法

    <?php//原理概念请看我的上一篇随笔(http://www.cnblogs.com/tujia/p/5416614.html)或直接百度 /** * 接口:hash(哈希插口).distri ...

  2. 7月目标 socket , 一致性哈希算法 ; mongodb分片; 分布式消息队列; 中间件的使用场景

      分布式的基础:一致性哈希  路由算法的一致性hash http://www.jiacheo.org/blog/174 http://www.tuicool.com/articles/vQVbmai ...

  3. Tornado 自定义session,与一致性哈希 ,基于redis 构建分布式 session框架

    Tornado 自定义session,与一致性哈希 ,基于redis 构建分布式 session import tornado.ioloop import tornado.web from myhas ...

  4. 分布式_理论_08_Consistent Hash(一致性哈希算法)

    一.前言 五.参考资料 1.分布式理论(八)—— Consistent Hash(一致性哈希算法)

  5. memcached分布式一致性哈希算法

    <span style="font-family: FangSong_GB2312; background-color: rgb(255, 255, 255);">如果 ...

  6. .net的一致性哈希实现

    最近在项目的微服务架构推进过程中,一个新的服务需要动态伸缩的弹性部署,所有容器化示例组成一个大的工作集群,以分布式处理的方式来完成一项工作,在集群中所有节点的任务分配过程中,由于集群工作节点需要动态增 ...

  7. 一致性哈希算法与Java实现

    原文:http://blog.csdn.net/wuhuan_wp/article/details/7010071 一致性哈希算法是分布式系统中常用的算法.比如,一个分布式的存储系统,要将数据存储到具 ...

  8. 五分钟理解一致性哈希算法(consistent hashing)

    转载请说明出处:http://blog.csdn.net/cywosp/article/details/23397179 一致性哈希算法在1997年由麻省理工学院提出的一种分布式哈希(DHT)实现算法 ...

  9. 每天进步一点点——五分钟理解一致性哈希算法(consistent hashing)

    转载请说明出处:http://blog.csdn.net/cywosp/article/details/23397179     一致性哈希算法在1997年由麻省理工学院提出的一种分布式哈希(DHT) ...

随机推荐

  1. 6个重要的.NET概念: - 堆栈,堆,值类型,引用类型,装箱和拆箱(转)

    今天在Code Project上面看到一篇文章<6 important .NET concepts: - Stack, heap, Value types, reference types, b ...

  2. Java的深拷贝和浅拷贝

    关于Java的深拷贝和浅拷贝,简单来说就是创建一个和已知对象一模一样的对象.可能日常编码过程中用的不多,但是这是一个面试经常会问的问题,而且了解深拷贝和浅拷贝的原理,对于Java中的所谓值传递或者引用 ...

  3. 1.Docker是什么?

    Docker官网是这样解释的: Docker is the company driving the container movement and the only container platform ...

  4. tp5 日志文件名称问题

    原文:http://www.upwqy.com/details/17.html 我的项目在运行一段时间后 我发现在日志中生成了 1508467147-20.log 这种文件名的日志 开始还以为是bug ...

  5. PLSQL Developer连接远程数据库的配置

    去Oracle的安装目录找到:D:\oracle\NETWORK\ADMIN这个路径下面的tnsnames.ora文件 修改文件: 这个是本地的 ORCL = (DESCRIPTION = (ADDR ...

  6. Java 多线程之哪个对象才是锁?

    问题背景 在感觉正常的使用ArrayList的迭代删除的操作的时候,发现了如下的崩溃日志: Caused by: java.util.ConcurrentModificationException a ...

  7. Spring与Akka的集成

    概述 近年来随着Spark的火热,Spark本身使用的开发语言Scala.用到的分布式内存文件系统Tachyon(现已更名为Alluxio)以及基于Actor并发编程模型的Akka都引起了大家的注意. ...

  8. 基于fitnesse浅析waferslim引擎

    最近在用fitnesse框架做自动化测试,简单总结一下,后边再补充内容. 1.fitnesse简介:后续补 略,见官网 http://www.fitnesse.org/ 2.waferslim引擎之p ...

  9. 深度学习——优化器算法Optimizer详解(BGD、SGD、MBGD、Momentum、NAG、Adagrad、Adadelta、RMSprop、Adam)

    在机器学习.深度学习中使用的优化算法除了常见的梯度下降,还有 Adadelta,Adagrad,RMSProp 等几种优化器,都是什么呢,又该怎么选择呢? 在 Sebastian Ruder 的这篇论 ...

  10. Nginx配置ThinkPHP下的url重写(隐藏入口)

    搭建好项目后,在网址上输入域名,只能访问首页,其他页面全是404. 在域名后面和控制器前面加上index.php就可以访问. 在tp5官网手册查找后进行配置修改. 打开nginx.conf 后 ,在s ...