1. <?php
  2. /**
  3. * Flexihash - A simple consistent hashing implementation for PHP.
  4. *
  5. * The MIT License
  6. *
  7. * Copyright (c) 2008 Paul Annesley
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining a copy
  10. * of this software and associated documentation files (the "Software"), to deal
  11. * in the Software without restriction, including without limitation the rights
  12. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. * copies of the Software, and to permit persons to whom the Software is
  14. * furnished to do so, subject to the following conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be included in
  17. * all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. * THE SOFTWARE.
  26. *
  27. * @author Paul Annesley
  28. * @link http://paul.annesley.cc/
  29. * @copyright Paul Annesley, 2008
  30. * @comment by MyZ (http://blog.csdn.net/mayongzhan)
  31. */
  32.  
  33. /**
  34. * A simple consistent hashing implementation with pluggable hash algorithms.
  35. *
  36. * @author Paul Annesley
  37. * @package Flexihash
  38. * @licence http://www.opensource.org/licenses/mit-license.php
  39. */
  40. class Flexihash
  41. {
  42.  
  43. /**
  44. * The number of positions to hash each target to.
  45. *
  46. * @var int
  47. * @comment 虚拟节点数,解决节点分布不均的问题
  48. */
  49. private $_replicas = 64;
  50.  
  51. /**
  52. * The hash algorithm, encapsulated in a Flexihash_Hasher implementation.
  53. * @var object Flexihash_Hasher
  54. * @comment 使用的hash方法 : md5,crc32
  55. */
  56. private $_hasher;
  57.  
  58. /**
  59. * Internal counter for current number of targets.
  60. * @var int
  61. * @comment 节点记数器
  62. */
  63. private $_targetCount = 0;
  64.  
  65. /**
  66. * Internal map of positions (hash outputs) to targets
  67. * @var array { position => target, ... }
  68. * @comment 位置对应节点,用于lookup中根据位置确定要访问的节点
  69. */
  70. private $_positionToTarget = array();
  71.  
  72. /**
  73. * Internal map of targets to lists of positions that target is hashed to.
  74. * @var array { target => [ position, position, ... ], ... }
  75. * @comment 节点对应位置,用于删除节点
  76. */
  77. private $_targetToPositions = array();
  78.  
  79. /**
  80. * Whether the internal map of positions to targets is already sorted.
  81. * @var boolean
  82. * @comment 是否已排序
  83. */
  84. private $_positionToTargetSorted = false;
  85.  
  86. /**
  87. * Constructor
  88. * @param object $hasher Flexihash_Hasher
  89. * @param int $replicas Amount of positions to hash each target to.
  90. * @comment 构造函数,确定要使用的hash方法和需拟节点数,虚拟节点数越多,分布越均匀,但程序的分布式运算越慢
  91. */
  92. public function __construct(Flexihash_Hasher $hasher = null, $replicas = null)
  93. {
  94. $this->_hasher = $hasher ? $hasher : new Flexihash_Crc32Hasher();
  95. if (!empty($replicas)) $this->_replicas = $replicas;
  96. }
  97.  
  98. /**
  99. * Add a target.
  100. * @param string $target
  101. * @chainable
  102. * @comment 添加节点,根据虚拟节点数,将节点分布到多个虚拟位置上
  103. */
  104. public function addTarget($target)
  105. {
  106. if (isset($this->_targetToPositions[$target]))
  107. {
  108. throw new Flexihash_Exception("Target '$target' already exists.");
  109. }
  110.  
  111. $this->_targetToPositions[$target] = array();
  112.  
  113. // hash the target into multiple positions
  114. for ($i = 0; $i < $this->_replicas; $i++)
  115. {
  116. $position = $this->_hasher->hash($target . $i);
  117. $this->_positionToTarget[$position] = $target; // lookup
  118. $this->_targetToPositions[$target] []= $position; // target removal
  119. }
  120.  
  121. $this->_positionToTargetSorted = false;
  122. $this->_targetCount++;
  123.  
  124. return $this;
  125. }
  126.  
  127. /**
  128. * Add a list of targets.
  129. * @param array $targets
  130. * @chainable
  131. */
  132. public function addTargets($targets)
  133. {
  134. foreach ($targets as $target)
  135. {
  136. $this->addTarget($target);
  137. }
  138.  
  139. return $this;
  140. }
  141.  
  142. /**
  143. * Remove a target.
  144. * @param string $target
  145. * @chainable
  146. */
  147. public function removeTarget($target)
  148. {
  149. if (!isset($this->_targetToPositions[$target]))
  150. {
  151. throw new Flexihash_Exception("Target '$target' does not exist.");
  152. }
  153.  
  154. foreach ($this->_targetToPositions[$target] as $position)
  155. {
  156. unset($this->_positionToTarget[$position]);
  157. }
  158.  
  159. unset($this->_targetToPositions[$target]);
  160.  
  161. $this->_targetCount--;
  162.  
  163. return $this;
  164. }
  165.  
  166. /**
  167. * A list of all potential targets
  168. * @return array
  169. */
  170. public function getAllTargets()
  171. {
  172. return array_keys($this->_targetToPositions);
  173. }
  174.  
  175. /**
  176. * Looks up the target for the given resource.
  177. * @param string $resource
  178. * @return string
  179. */
  180. public function lookup($resource)
  181. {
  182. $targets = $this->lookupList($resource, 1);
  183. if (empty($targets)) throw new Flexihash_Exception('No targets exist');
  184. return $targets[0];
  185. }
  186.  
  187. /**
  188. * Get a list of targets for the resource, in order of precedence.
  189. * Up to $requestedCount targets are returned, less if there are fewer in total.
  190. *
  191. * @param string $resource
  192. * @param int $requestedCount The length of the list to return
  193. * @return array List of targets
  194. * @comment 查找当前的资源对应的节点,
  195. * 节点为空则返回空,节点只有一个则返回该节点,
  196. * 对当前资源进行hash,对所有的位置进行排序,在有序的位置列上寻找当前资源的位置
  197. * 当全部没有找到的时候,将资源的位置确定为有序位置的第一个(形成一个环)
  198. * 返回所找到的节点
  199. */
  200. public function lookupList($resource, $requestedCount)
  201. {
  202. if (!$requestedCount)
  203. throw new Flexihash_Exception('Invalid count requested');
  204.  
  205. // handle no targets
  206. if (empty($this->_positionToTarget))
  207. return array();
  208.  
  209. // optimize single target
  210. if ($this->_targetCount == 1)
  211. return array_unique(array_values($this->_positionToTarget));
  212.  
  213. // hash resource to a position
  214. $resourcePosition = $this->_hasher->hash($resource);
  215.  
  216. $results = array();
  217. $collect = false;
  218.  
  219. $this->_sortPositionTargets();
  220.  
  221. // search values above the resourcePosition
  222. foreach ($this->_positionToTarget as $key => $value)
  223. {
  224. // start collecting targets after passing resource position
  225. if (!$collect && $key > $resourcePosition)
  226. {
  227. $collect = true;
  228. }
  229.  
  230. // only collect the first instance of any target
  231. if ($collect && !in_array($value, $results))
  232. {
  233. $results []= $value;
  234. }
  235.  
  236. // return when enough results, or list exhausted
  237. if (count($results) == $requestedCount || count($results) == $this->_targetCount)
  238. {
  239. return $results;
  240. }
  241. }
  242.  
  243. // loop to start - search values below the resourcePosition
  244. foreach ($this->_positionToTarget as $key => $value)
  245. {
  246. if (!in_array($value, $results))
  247. {
  248. $results []= $value;
  249. }
  250.  
  251. // return when enough results, or list exhausted
  252. if (count($results) == $requestedCount || count($results) == $this->_targetCount)
  253. {
  254. return $results;
  255. }
  256. }
  257.  
  258. // return results after iterating through both "parts"
  259. return $results;
  260. }
  261.  
  262. public function __toString()
  263. {
  264. return sprintf(
  265. '%s{targets:[%s]}',
  266. get_class($this),
  267. implode(',', $this->getAllTargets())
  268. );
  269. }
  270.  
  271. // ----------------------------------------
  272. // private methods
  273.  
  274. /**
  275. * Sorts the internal mapping (positions to targets) by position
  276. */
  277. private function _sortPositionTargets()
  278. {
  279. // sort by key (position) if not already
  280. if (!$this->_positionToTargetSorted)
  281. {
  282. ksort($this->_positionToTarget, SORT_REGULAR);
  283. $this->_positionToTargetSorted = true;
  284. }
  285. }
  286.  
  287. }
  288.  
  289. /**
  290. * Hashes given values into a sortable fixed size address space.
  291. *
  292. * @author Paul Annesley
  293. * @package Flexihash
  294. * @licence http://www.opensource.org/licenses/mit-license.php
  295. */
  296. interface Flexihash_Hasher
  297. {
  298.  
  299. /**
  300. * Hashes the given string into a 32bit address space.
  301. *
  302. * Note that the output may be more than 32bits of raw data, for example
  303. * hexidecimal characters representing a 32bit value.
  304. *
  305. * The data must have 0xFFFFFFFF possible values, and be sortable by
  306. * PHP sort functions using SORT_REGULAR.
  307. *
  308. * @param string
  309. * @return mixed A sortable format with 0xFFFFFFFF possible values
  310. */
  311. public function hash($string);
  312.  
  313. }
  314.  
  315. /**
  316. * Uses CRC32 to hash a value into a signed 32bit int address space.
  317. * Under 32bit PHP this (safely) overflows into negatives ints.
  318. *
  319. * @author Paul Annesley
  320. * @package Flexihash
  321. * @licence http://www.opensource.org/licenses/mit-license.php
  322. */
  323. class Flexihash_Crc32Hasher
  324. implements Flexihash_Hasher
  325. {
  326.  
  327. /* (non-phpdoc)
  328. * @see Flexihash_Hasher::hash()
  329. */
  330. public function hash($string)
  331. {
  332. return crc32($string);
  333. }
  334.  
  335. }
  336.  
  337. /**
  338. * Uses CRC32 to hash a value into a 32bit binary string data address space.
  339. *
  340. * @author Paul Annesley
  341. * @package Flexihash
  342. * @licence http://www.opensource.org/licenses/mit-license.php
  343. */
  344. class Flexihash_Md5Hasher
  345. implements Flexihash_Hasher
  346. {
  347.  
  348. /* (non-phpdoc)
  349. * @see Flexihash_Hasher::hash()
  350. */
  351. public function hash($string)
  352. {
  353. return substr(md5($string), 0, 8); // 8 hexits = 32bit
  354.  
  355. // 4 bytes of binary md5 data could also be used, but
  356. // performance seems to be the same.
  357. }
  358.  
  359. }
  360.  
  361. /**
  362. * An exception thrown by Flexihash.
  363. *
  364. * @author Paul Annesley
  365. * @package Flexihash
  366. * @licence http://www.opensource.org/licenses/mit-license.php
  367. */
  368. class Flexihash_Exception extends Exception
  369. {
  370. }

PHP 实现 一致性哈希 算法(转的)的更多相关文章

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

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

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

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

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

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

  4. 一致性哈希算法以及其PHP实现

    在做服务器负载均衡时候可供选择的负载均衡的算法有很多,包括:  轮循算法(Round Robin).哈希算法(HASH).最少连接算法(Least Connection).响应速度算法(Respons ...

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

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

  6. 一致性哈希算法(consistent hashing)【转】

    一致性哈希算法 来自:http://blog.csdn.net/cywosp/article/details/23397179       一致性哈希算法在1997年由麻省理工学院提出的一种分布式哈希 ...

  7. 一致性哈希算法学习及JAVA代码实现分析

    1,对于待存储的海量数据,如何将它们分配到各个机器中去?---数据分片与路由 当数据量很大时,通过改善单机硬件资源的纵向扩充方式来存储数据变得越来越不适用,而通过增加机器数目来获得水平横向扩展的方式则 ...

  8. 一致性哈希算法——算法解决的核心问题是当slot数发生变化时,能够尽量少的移动数据

    一致性哈希算法 摘自:http://blog.codinglabs.org/articles/consistent-hashing.html 算法简述 一致性哈希算法(Consistent Hashi ...

  9. 一致性哈希算法原理及Java实现

     一致性哈希算法在1997年由麻省理工学院提出的一种分布式哈希(DHT)实现算法,设计目标是为了解决因特网中的热点(Hot spot)问题,初衷和CARP十分类似.一致性哈希修正了CARP使用的简 单 ...

  10. _00013 一致性哈希算法 Consistent Hashing 新的讨论,并出现相应的解决

    笔者博文:妳那伊抹微笑 博客地址:http://blog.csdn.net/u012185296 个性签名:世界上最遥远的距离不是天涯,也不是海角,而是我站在妳的面前.妳却感觉不到我的存在 技术方向: ...

随机推荐

  1. linux 下如何查看和踢除正在登陆的其它用户 ==>Linux下用于查看系统当前登录用户信息的4种方法

    在linux系统中用pkill命令踢出在线登录用户 由于linux服务器允许多用户登录,公司很多人知道密码,工作造成一定的障碍 所以需要有时踢出指定的用户 1/#who   查出当前有那些终端登录(用 ...

  2. Hessian原理分析

    一.      远程通讯协议的基本原理 网络通信需要做的就是将流从一台计算机传输到另外一台计算机,基于传输协议和网络 IO 来实现,其中传输协议比较出名的有 http . tcp . udp 等等, ...

  3. 37.寻找丑数[Ugly numbers]

    [题目] 我们把只包含质因子2.3和5的数称作丑数(Ugly Number),例如:2,3,4,5,6,8,9,10,12,15,等,习惯上我们把1当做是第一个丑数.求按从小到大的顺序的第1500个丑 ...

  4. Android 中的code sign

    Android 中和ios中都有code sign.它们的目的一样,都是要保证程序的可靠性,最基本实现原理也一样.但是sign的过程比较不同. 下面记录一点Android sign的重要知识. 请参看 ...

  5. mysql show

    1.show命令语法 SHOW {BINARY | MASTER} LOGS SHOW BINLOG EVENTS [IN 'log_name'] [FROM pos] [LIMIT [offset, ...

  6. 1.django笔记之django基础

    一.django简介 Django是一个开放源代码的Web应用框架,由Python写成.采用了MVC的软件设计模式,即模型M,视图V和控制器C.它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内 ...

  7. CentOS6.5安装MySql5.5

    最近在CentOS上安装MySql,本来以为yum安装会很简单,但是却花了自己不少时间,所以决定和大家分享下. 首先,安装MySql源! 下载地址:http://dev.mysql.com/downl ...

  8. CityGML文件格式

    1 LOD3中,wall是由cuboid组成的,一个墙面包括8个面,分为wall-1, wall-2...wall-8,door也是,因此他们都是multisurface (一般由8个面片组成). 在 ...

  9. jQuery基础DOM和CSS操作

    $('#box').html();//获取 html 内容$('#box').text();//获取文本内容,会自动清理 html 标签$('#box').html('<em>www.li ...

  10. 图像边缘检测——Sobel算子

    边缘是图像最基本的特征,其在计算机视觉.图像分析等应用中起着重要的作用,这是因为图像的边缘包含了用于识别的有用信息,是图像分析和模式识别的主要特征提取手段. 1.何为“图像边缘”? 在图像中,“边缘” ...