python 一致性哈希 分布式
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 一致性哈希 分布式的更多相关文章
- php实现一致性哈希算法
<?php//原理概念请看我的上一篇随笔(http://www.cnblogs.com/tujia/p/5416614.html)或直接百度 /** * 接口:hash(哈希插口).distri ...
- 7月目标 socket , 一致性哈希算法 ; mongodb分片; 分布式消息队列; 中间件的使用场景
分布式的基础:一致性哈希 路由算法的一致性hash http://www.jiacheo.org/blog/174 http://www.tuicool.com/articles/vQVbmai ...
- Tornado 自定义session,与一致性哈希 ,基于redis 构建分布式 session框架
Tornado 自定义session,与一致性哈希 ,基于redis 构建分布式 session import tornado.ioloop import tornado.web from myhas ...
- 分布式_理论_08_Consistent Hash(一致性哈希算法)
一.前言 五.参考资料 1.分布式理论(八)—— Consistent Hash(一致性哈希算法)
- memcached分布式一致性哈希算法
<span style="font-family: FangSong_GB2312; background-color: rgb(255, 255, 255);">如果 ...
- .net的一致性哈希实现
最近在项目的微服务架构推进过程中,一个新的服务需要动态伸缩的弹性部署,所有容器化示例组成一个大的工作集群,以分布式处理的方式来完成一项工作,在集群中所有节点的任务分配过程中,由于集群工作节点需要动态增 ...
- 一致性哈希算法与Java实现
原文:http://blog.csdn.net/wuhuan_wp/article/details/7010071 一致性哈希算法是分布式系统中常用的算法.比如,一个分布式的存储系统,要将数据存储到具 ...
- 五分钟理解一致性哈希算法(consistent hashing)
转载请说明出处:http://blog.csdn.net/cywosp/article/details/23397179 一致性哈希算法在1997年由麻省理工学院提出的一种分布式哈希(DHT)实现算法 ...
- 每天进步一点点——五分钟理解一致性哈希算法(consistent hashing)
转载请说明出处:http://blog.csdn.net/cywosp/article/details/23397179 一致性哈希算法在1997年由麻省理工学院提出的一种分布式哈希(DHT) ...
随机推荐
- 九九乘法表的实现--JAVA基础
JAVA算法实现:输出九九乘法表 Jiujiu.java: package com.qkys.www; public class Jiujiu { public static void main(St ...
- TestLink和RedMine的集成
1. TestLink的安装 1.1. TestLink简介 TestLink是一个php语言开发的开源免费的测试管理工具,包括产品测试需求,测试计划,测试用例的创建和执行, ...
- mongodb在windows下安装启动
mongodb安装 mongodb配置 创建几个文件夹具体如下:数据库路径(\data\db\目录).日志路径(\data\log\目录)和日志文件(mongod.log文件)c:\data\log\ ...
- java 关键字final static native详解
java 关键字native static final详解 一.final 根据程序上下文环境,Java关键字final有"这是无法改变的"或者"终态的"含义, ...
- sql语句转为Model
在跟数据库打交道的时候,有一个常用的应用,就是把数据库中的表转为程序中的对象,也就是说表中的列转为对象的属性.对于字段比较少的,我们可以直接复制过去改,但是字段数比较多的时候,借助工具类实现比较方便而 ...
- sharepoint 2013实践
之前在一篇文章中说过了SharePoint环境的安装.那么如何使用SharePoint开发一个站点呢?这就是本篇所要阐述的问题. 在如何具体操作之前,我们先来普及下SharePoint基础知识.Far ...
- IE浏览器右键菜单插件开发(上篇)——自定义一个IE右键菜单项
要做一个IE右键浏览器插件,得3步走. 第一,在IE右键菜单上添加自定义菜单名称,是通过注册表实现的,如下: string regkey = @"Software\Microsoft\Int ...
- 在eclipse中API的封装和调用
自己写的API的封装和调用:1.写好api的方法的实现类.2.抽取一个javadoc文档.file->Export->java->javadoc->finish->Yes ...
- 自增ID算法snowflake(雪花)
在数据库主键设计上,比较常见的方法是采用自增ID(1开始,每次加1)和生成GUID.生成GUID的方式虽然简单,但是由于采用的是无意义的字符串,推测会在数据量增大时造成访问过慢,在基础互联网的系统设计 ...
- 安装paramiko
前记: 各种奇葩事情都让我遇上了... 1.准备: 1>需要安装python 2>需要安装PyCrypto 2.安装python---省略 3.安装PyCrypto 1>检查pyth ...