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. [SDOI2012]Longge的问题

    题目大意: 网址:https://www.luogu.org/problemnew/show/P2303 大意:给定一个N,求\(\Sigma_{i=1}^N gcd(i, N);\). 题目解法: ...

  2. C#多线程编程(6)--线程安全2 互锁构造Interlocked

    在线程安全1中,我介绍了线程同步的意义和一种实现线程同步的方法:volatile.volatile关键字属于原子操作的一种,若对一个关键字使用volatile,很多时候会显得很"浪费&quo ...

  3. C++中不同变量、函数在内存中的内存情况《转》

    一.一个C++编译的程序占用的内存分为以下几个部分 1.栈区:由编译器自动分配 存放函数的参数值,局部变量的值等,操作方式类似于数据结构中的栈. 2.堆区:一般由程序员分配释放,若程序员不释放,程序结 ...

  4. PHP 获取访问来源

    原文:http://www.upwqy.com/details/16.html $_SERVER['HTTP_REFERER'] 通过这个全局变量可以获取访问的链接是来源于哪里 比如说从博客园 htt ...

  5. react-todoMVC脚手架

    webpack.config.js var path = require('path'); // node中的 路径解析的模块 const HtmlWebpackPlugin =require('ht ...

  6. python模板:自动化执行测试函数

    #!/bin/python #example 1.1 #applay def function(a,b): print(a,b) def example1(): apply(function, (&q ...

  7. Java集合框架(一)

    原文  http://www.jianshu.com/p/e31fb2600e4f 集合类存放于java.util包中,集合类存放的都是对象的引用,而非对象本身,出于表达上的便利,我们称集合中的对象就 ...

  8. Could not get dialect instance.

    一般此错误都是和数据库有关,请确认数据库配置文件是否配置正确,或者确认数据库是否连接正常

  9. Python基础教程3——教你用Python做个简单的加密程序(还基础什么呀,直接来练习吧,带源码)

    因为发现基础教程我之前推荐的那个网站就已经很完善了,就不重复写了,所以本汪来一起做练习吧. 一.加密原理 记得当时我学c++的时候,学到输入输出流的时候,当时王老师就教我们写了一个小的加密程序,所以这 ...

  10. python 全栈开发,Day4

    python之文件操作 一.文件操作基本流程 计算机系统分为:计算机硬件,操作系统,应用程序三部分. 我们用python或其他语言编写的应用程序若想要把数据永久保存下来,必须要保存于硬盘中,这就涉及到 ...