hash_ring

  1. # -*- coding: utf-8 -*-
  2. """
  3. hash_ring
  4. ~~~~~~~~~~~~~~
  5. Implements consistent hashing that can be used when
  6. the number of server nodes can increase or decrease (like in memcached).
  7.  
  8. Consistent hashing is a scheme that provides a hash table functionality
  9. in a way that the adding or removing of one slot
  10. does not significantly change the mapping of keys to slots.
  11.  
  12. More information about consistent hashing can be read in these articles:
  13.  
  14. "Web Caching with Consistent Hashing":
  15. http://www8.org/w8-papers/2a-webserver/caching/paper2.html
  16.  
  17. "Consistent hashing and random trees:
  18. Distributed caching protocols for relieving hot spots on the World Wide Web (1997)":
  19. http://citeseerx.ist.psu.edu/legacymapper?did=38148
  20.  
  21. Example of usage::
  22.  
  23. memcache_servers = ['192.168.0.246:11212',
  24. '192.168.0.247:11212',
  25. '192.168.0.249:11212']
  26.  
  27. ring = HashRing(memcache_servers)
  28. server = ring.get_node('my_key')
  29.  
  30. :copyright: 2008 by Amir Salihefendic.
  31. :license: BSD
  32. """
  33.  
  34. import math
  35. import sys
  36. from bisect import bisect
  37.  
  38. if sys.version_info >= (2, 5):
  39. import hashlib
  40. md5_constructor = hashlib.md5
  41. else:
  42. import md5
  43. md5_constructor = md5.new
  44.  
  45. class HashRing(object):
  46.  
  47. def __init__(self, nodes=None, weights=None):
  48. """`nodes` is a list of objects that have a proper __str__ representation.
  49. `weights` is dictionary that sets weights to the nodes. The default
  50. weight is that all nodes are equal.
  51. """
  52. self.ring = dict()
  53. self._sorted_keys = []
  54.  
  55. self.nodes = nodes
  56.  
  57. if not weights:
  58. weights = {}
  59. self.weights = weights
  60.  
  61. self._generate_circle()
  62.  
  63. def _generate_circle(self):
  64. """Generates the circle.
  65. """
  66. total_weight = 0
  67. for node in self.nodes:
  68. total_weight += self.weights.get(node, 1)
  69.  
  70. for node in self.nodes:
  71. weight = 1
  72.  
  73. if node in self.weights:
  74. weight = self.weights.get(node)
  75.  
  76. factor = math.floor((40*len(self.nodes)*weight) / total_weight);
  77.  
  78. for j in range(0, int(factor)):
  79. b_key = self._hash_digest( '%s-%s' % (node, j) )
  80.  
  81. for i in range(0, 3):
  82. key = self._hash_val(b_key, lambda x: x+i*4)
  83. self.ring[key] = node
  84. self._sorted_keys.append(key)
  85.  
  86. self._sorted_keys.sort()
  87.  
  88. def get_node(self, string_key):
  89. """Given a string key a corresponding node in the hash ring is returned.
  90.  
  91. If the hash ring is empty, `None` is returned.
  92. """
  93. pos = self.get_node_pos(string_key)
  94. if pos is None:
  95. return None
  96. return self.ring[ self._sorted_keys[pos] ]
  97.  
  98. def get_node_pos(self, string_key):
  99. """Given a string key a corresponding node in the hash ring is returned
  100. along with it's position in the ring.
  101.  
  102. If the hash ring is empty, (`None`, `None`) is returned.
  103. """
  104. if not self.ring:
  105. return None
  106.  
  107. key = self.gen_key(string_key)
  108.  
  109. nodes = self._sorted_keys
  110. pos = bisect(nodes, key)
  111.  
  112. if pos == len(nodes):
  113. return 0
  114. else:
  115. return pos
  116.  
  117. def iterate_nodes(self, string_key, distinct=True):
  118. """Given a string key it returns the nodes as a generator that can hold the key.
  119.  
  120. The generator iterates one time through the ring
  121. starting at the correct position.
  122.  
  123. if `distinct` is set, then the nodes returned will be unique,
  124. i.e. no virtual copies will be returned.
  125. """
  126. if not self.ring:
  127. yield None, None
  128.  
  129. returned_values = set()
  130. def distinct_filter(value):
  131. if str(value) not in returned_values:
  132. returned_values.add(str(value))
  133. return value
  134.  
  135. pos = self.get_node_pos(string_key)
  136. for key in self._sorted_keys[pos:]:
  137. val = distinct_filter(self.ring[key])
  138. if val:
  139. yield val
  140.  
  141. for i, key in enumerate(self._sorted_keys):
  142. if i < pos:
  143. val = distinct_filter(self.ring[key])
  144. if val:
  145. yield val
  146.  
  147. def gen_key(self, key):
  148. """Given a string key it returns a long value,
  149. this long value represents a place on the hash ring.
  150.  
  151. md5 is currently used because it mixes well.
  152. """
  153. b_key = self._hash_digest(key)
  154. return self._hash_val(b_key, lambda x: x)
  155.  
  156. def _hash_val(self, b_key, entry_fn):
  157. return (( b_key[entry_fn(3)] << 24)
  158. |(b_key[entry_fn(2)] << 16)
  159. |(b_key[entry_fn(1)] << 8)
  160. | b_key[entry_fn(0)] )
  161.  
  162. def _hash_digest(self, key):
  163. m = md5_constructor()
  164. m.update(bytes(key,encoding='utf-8'))
  165. #return map(ord, m.digest())
  166. return list(m.digest())
  167.  
  168. '''
  169. memcache_servers = ['192.168.0.246:11212',
  170. '192.168.0.247:11212',
  171. '192.168.0.249:11212']
  172.  
  173. ring = HashRing(memcache_servers)
  174. server = ring.get_node('my_key')
  175. '''
  176.  
  177. # 增加权重
  178.  
  179. memcache_servers = ['192.168.0.246:11212',
  180. '192.168.0.247:11212',
  181. '192.168.0.249:11212']
  182. weights = {
  183. '192.168.0.246:11212': 1,
  184. '192.168.0.247:11212': 2,
  185. '192.168.0.249:11212': 1
  186. }
  187.  
  188. ring = HashRing(memcache_servers, weights)
  189. server = ring.get_node('my_key')
  190. 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. n人围成一圈报数

    题目:有n个人围成一圈,顺序排号.从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来的第几号的那位 思路:用一个数组存这n个人,里面的初始状态全设为1,表示都还在圈子里面. ...

  2. css图片的相关操作

    css图片的相关操作 1.案例源码 <!DOCTYPE html><html lang="en"><head> <meta charset ...

  3. 基于puppet分布式集群管理公有云多租户的架构浅谈

    基于puppet分布式集群管理公有云多租户的架构浅谈 一.架构介绍   在此架构中,每个租户的业务集群部署一台puppet-master作为自己所在业务集群的puppet的主服务器,在每个业务集群所拥 ...

  4. 【BZOJ3196】二逼平衡树(树状数组,线段树)

    [BZOJ3196]二逼平衡树(树状数组,线段树) 题面 BZOJ题面 题解 如果不存在区间修改操作: 搞一个权值线段树 区间第K大--->直接在线段树上二分 某个数第几大--->查询一下 ...

  5. 【BZOJ1004】Cards(组合数学,Burnside引理)

    [BZOJ1004]Cards(组合数学,Burnside引理) 题面 Description 小春现在很清闲,面对书桌上的N张牌,他决定给每张染色,目前小春只有3种颜色:红色,蓝色,绿色.他询问Su ...

  6. 对网易云音乐参数(params,encSecKey)的分析

    我们如果对网易云音乐进行爬虫的话,我们会发现,提交的参数是(params,encSecKey),然而这两个参数是一串很长的东西 我们要对网易云进行爬虫,那么就一定要将这两个参数弄明白,然后才可以进行爬 ...

  7. 九度OJ题目1105:字符串的反码

    tips:scanf,cin输入字符串遇到空格就停止,所以想输入一行字符并保留最后的"\0"还是用gets()函数比较好,九度OJ真操蛋,true?没有这个关键字,还是用1吧,还是 ...

  8. vue.js 视频播放

    最近心学习vue.js开发,video开发播放! 使用第三方的封装:https://www.npmjs.com/package/vue-video-player: 1. npm install vue ...

  9. Java反射总结

    一. 获取Class对象的3种方法: 1. Class.forName("");例如:Class.forName("java.lang.String"); 2. ...

  10. 关于classpath

    classpath是用来设计JAVA类文件(.class)所在的路径 classpath的主要作用就是当你在一个shell窗口下执行命令时,可以从在classpath中设置的目录搜索,不用一层再一层的 ...