1. 一、概述
    Memcachedmysql一样,是一款客户端/服务器端(C/S)系统管理软件,有IP、端口,一旦启动,服务器就一直处于可用状态。
    Mysql是通过SQL语句管理“磁盘中”的文件,Memcached是通过客户端发送的命令管理“内存中缓存”的数据。 
    需要缓存的对象或数据以 key/value 对的形式保存在服务器端,key的值通过hashhash算法的意义在于提供一种快速存取数据的方法,它用一种算法建立键值与真实值之间的对应关系)进行转换,把value传递到对应的具体的某台服务器上。

  1. Memcached的分布式不是在服务器端实现的,而是在客户端应用中实现的,即通过内置算法制定目标数据的节点。
    多台服务器之间是没有任何通信联系的,每台服务器只是对自己的数据进行管理。

  1. * 布置多台Memcached服务器。怎么确定一个数据应该保存到哪台服务器上?
    * 方案一:普通Hash分布。
    * 方案二:一致性Hash分布。
    理论参考:https://blog.csdn.net/u011489043/article/details/78944985
  2.  
  3. 二、简单hash算法
  1. function simpleHash(string $key)
  2. {
  3. $md5 = md5($key);
  4. $hash = 0;
  5. for ($i = 0; $i < strlen($md5); $i++) {
  6. $hash += ord($md5{$i});
  7. }
  8. return $hash;
  9. }

三、普通hash分布

  1. /**
  2. * 普通Hash分布
  3. * 取模算法算法的原理是:hash(key)%N
  4. */
  5. $servers = ['192.168.1.12', '192.168.1.20'];
  6. echo PHP_EOL . '普通hash算法' . PHP_EOL;
  7. echo 'save key1 in server:' . $servers[simpleHash('this is key1') % 2] . PHP_EOL;
  8. echo 'save key2 in server:' . $servers[simpleHash('this is key2') % 2] . PHP_EOL;

四、一致性哈希

  1. * 一致哈希(Consistent Hashing)算法,分布式系统负载均衡的首选算法
    *
    * 步骤:
    * 1、通常,一个缓存数据的key经过hash后会得到一个32位的值,
    * 将一个32位整数(0~2^32-1)想象成一个环
    * 2、通过hash函数把可以处理成整数,在环中找到一个位置与之对应
    * 3、使用hash函数处理服务器使用的IP地址,把Memcached服务器群也映射到环上
    * 4、把数据映射到服务器上
    * 沿着圆环顺时针方向的key出发,直到遇到一个服务器为止,把key对应的数据保存到这个服务器上
    * 5、移除服务器
    * 受影响的仅是当前服务器节点沿着逆时针出发直到遇到下一个服务器之间的数据,
    * 把这些数据按操作4重新映射即可
    * 6、添加服务器
    * 受影响的是当前服务器节点沿着逆时针出发直到遇到下一个服务器之间的数据,
    * 重新映射
  1. PHP的一种实现
  1. class FlexiHash
  2. {
  3. // 保存服务器列表
  4. private $serverList = [];
  5. // 记录服务器列表是否已经排过序
  6. private $isSorted = false;
  7.  
  8. /**
  9. * 添加一个服务器到服务器列表中
  10. */
  11. public function addServer($server)
  12. {
  13. $hash = simpleHash($server);
  14. if (!isset($this->serverList[$hash])) {
  15. $this->serverList[$hash] = $server;
  16. }
  17. $this->isSorted = false;
  18. return true;
  19. }
  20.  
  21. /**
  22. * 从服务器列表中删除一个服务器
  23. */
  24. public function removeServer($server)
  25. {
  26. $hash = simpleHash($server);
  27. if (isset($this->serverList[$hash])) {
  28. unset($this->serverList[$hash]);
  29. }
  30. $this->isSorted = false;
  31. return true;
  32. }
  33.  
  34. /**
  35. * 在当前的服务器列表中找到合适的服务器存放数据
  36. * 逆时针的圆环
  37. */
  38. public function lookup($key)
  39. {
  40. $hash = simpleHash($key);
  41. if (!$this->isSorted) {
  42. krsort($this->serverList, SORT_NUMERIC);
  43. $this->isSorted = true;
  44. }
  45. foreach ($this->serverList as $pos => $server) {
  46. if ($hash >= $pos) {
  47. return $server;
  48. }
  49. }
  50. $index = array_search(min($this->serverList), $this->serverList);
  51. return $this->serverList[$index];
  52. }
  53. }
  54.  
  55. // 测试
  56. echo PHP_EOL . '一致性hash算法' . PHP_EOL;
  57. $hserver = new FlexiHash();
  58. $hserver->addServer('192.168.1.1');
  59. $hserver->addServer('192.168.1.2');
  60. $hserver->addServer('192.168.1.3');
  61. $hserver->addServer('192.168.1.4');
  62. $hserver->addServer('192.168.1.5');
  63. echo '初始分布' . PHP_EOL;
  64. echo 'save key1 in server:' . $hserver->lookup('key1') . PHP_EOL;
  65. echo 'save key2 in server:' . $hserver->lookup('key2') . PHP_EOL;
  66. echo '===============================================' . PHP_EOL;
  67. $hserver->removeServer('192.168.1.4');
  68. echo '删除一台服务器后' . PHP_EOL;
  69. echo 'save key1 in server:' . $hserver->lookup('key1') . PHP_EOL;
  70. echo 'save key2 in server:' . $hserver->lookup('key2') . PHP_EOL;
  71. echo '===============================================' . PHP_EOL;
  72. $hserver->addServer('192.168.1.6');
  73. echo '添加一台服务器后' . PHP_EOL;
  74. echo 'save key1 in server:' . $hserver->lookup('key1') . PHP_EOL;
  75. echo 'save key2 in server:' . $hserver->lookup('key2') . PHP_EOL;

  1. 另一种实现 增加虚拟节点
  1. class ConsistentHashing
  2. {
  3. // 每个节点对应虚拟节点数
  4. const VIRTUAL_NODES = 32;
  5. // server 拥有的hash(节点+虚拟节点)
  6. protected $nodes = [];
  7. // hash映射server
  8. protected $position = [];
  9. // 记录服务器列表是否已经排过序
  10. protected $isSorted = false;
  11.  
  12. /**
  13. * 添加节点
  14. */
  15. public function addNode($server)
  16. {
  17. if (isset($this->nodes[$server])) {
  18. return;
  19. }
  20.  
  21. // 添加节点和虚拟节点
  22. for ($i = 0; $i < self::VIRTUAL_NODES; $i++) {
  23. $hash = $this->myHash($server . '#' . $i);
  24. $this->position[$hash] = $server;
  25. $this->nodes[$server][] = $hash;
  26. }
  27.  
  28. $this->isSorted = false;
  29. }
  30.  
  31. /**
  32. * 删除节点
  33. */
  34. public function delNode($server)
  35. {
  36. if (!isset($this->nodes[$server])) return;
  37.  
  38. // 循环删除虚拟节点
  39. foreach ($this->nodes[$server] as $val) {
  40. unset($this->position[$val]);
  41. }
  42.  
  43. // 删除节点
  44. unset($this->nodes[$server]);
  45.  
  46. $this->isSorted = false;
  47. }
  48.  
  49. /**
  50. * 定位key所属节点
  51. * 顺时针环
  52. */
  53. public function lookup($key)
  54. {
  55. if (!$this->isSorted) {
  56. $this->sortPosition();
  57. $this->isSorted = true;
  58. }
  59.  
  60. $hash = $this->myHash($key);
  61.  
  62. // 先取圆环上最小的一个节点,当成结果
  63. $server = current($this->position);
  64.  
  65. // 循环获取相近的节点
  66. foreach ($this->position as $pos => $val) {
  67. if ($hash <= $pos) {
  68. $server = $val;
  69. break;
  70. }
  71. }
  72.  
  73. return $server;
  74. }
  75.  
  76. /**
  77. * 按键名顺序排序
  78. */
  79. private function sortPosition()
  80. {
  81. ksort($this->position);
  82. }
  83.  
  84. /**
  85. * 自定义哈希函数,把key转为32位符号整数
  86. */
  87. private function myHash($key)
  88. {
  89.  
  90. // return sprintf('%u', crc32($key));
  91. return simpleHash($key);
  92. }
  93. }
  94.  
  95. // 测试
  96. echo PHP_EOL . '另一种hash一致性算法' . PHP_EOL;
  97. $ch = new ConsistentHashing();
  98. $ch->addNode('192.168.1.1');
  99. $ch->addNode('192.168.1.2');
  100. $ch->addNode('192.168.1.3');
  101. $ch->addNode('192.168.1.4');
  102. $ch->addNode('192.168.1.5');
  103. echo '初始化' . PHP_EOL;
  104. echo 'save key1 in server:' . $ch->lookup('key1') . PHP_EOL;
  105. echo 'save key2 in server:' . $ch->lookup('key2') . PHP_EOL;
  106. echo '==========================================' . PHP_EOL;
  107. $ch->delNode('192.168.1.4');
  108. echo '删除节点后' . PHP_EOL;
  109. echo 'save key1 in server:' . $ch->lookup('key1') . PHP_EOL;
  110. echo 'save key2 in server:' . $ch->lookup('key2') . PHP_EOL;
  111. echo '==========================================' . PHP_EOL;
  112. $ch->addNode('192.168.1.6');
  113. echo '添加一台服务器后' . PHP_EOL;
  114. echo 'save key1 in server:' . $ch->lookup('key1') . PHP_EOL;
  115. echo 'save key2 in server:' . $ch->lookup('key2') . PHP_EOL;

php hash算法实现memcached分布式的更多相关文章

  1. 一致性Hash算法在Redis分布式中的使用

    由于redis是单点,但是项目中不可避免的会使用多台Redis缓存服务器,那么怎么把缓存的Key均匀的映射到多台Redis服务器上,且随着缓存服务器的增加或减少时做到最小化的减少缓存Key的命中率呢? ...

  2. 一致性Hash算法在Memcached中的应用

    前言 大家应该都知道Memcached要想实现分布式只能在客户端来完成,目前比较流行的是通过一致性hash算法来实现.常规的方法是将server的hash值与server的总台数进行求余,即hash% ...

  3. Nginx+Memcache+一致性hash算法 实现页面分布式缓存(转)

    网站响应速度优化包括集群架构中很多方面的瓶颈因素,这里所说的将页面静态化.实现分布式高速缓存就是其中的一个很好的解决方案... 1)先来看看Nginx负载均衡 Nginx负载均衡依赖自带的 ngx_h ...

  4. (转) 一致性Hash算法在Memcached中的应用

    前言 大家应该都知道Memcached要想实现分布式只能在客户端来完成,目前比较流行的是通过一致性hash算法来实现.常规的方法是将 server的hash值与server的总台数进行求余,即hash ...

  5. 一致性hash算法在memcached中的使用

    一.概述 1.我们的memcacheclient(这里我看的spymemcache的源代码).使用了一致性hash算法ketama进行数据存储节点的选择.与常规的hash算法思路不同.仅仅是对我们要存 ...

  6. 一致性Hash算法介绍(分布式环境算法)

    32的整数环(这个环被称作一致性Hash环),根据节点名称的Hash值(其分布范围同样为0~232)将节点放置在这个Hash 环上.然后根据KEY值计算得到其Hash值(其分布范围也同样为0~232  ...

  7. 分布式缓存技术memcached学习(四)—— 一致性hash算法原理

    分布式一致性hash算法简介 当你看到“分布式一致性hash算法”这个词时,第一时间可能会问,什么是分布式,什么是一致性,hash又是什么.在分析分布式一致性hash算法原理之前,我们先来了解一下这几 ...

  8. 分布式缓存技术memcached学习系列(四)—— 一致性hash算法原理

    分布式一致性hash算法简介 当你看到"分布式一致性hash算法"这个词时,第一时间可能会问,什么是分布式,什么是一致性,hash又是什么.在分析分布式一致性hash算法原理之前, ...

  9. 分布式一致性hash算法

    写在前面  在学习Redis的集群内容时,看到这么一句话:Redis并没有使用一致性hash算法,而是引入哈希槽的概念.而分布式缓存Memcached则是使用分布式一致性hash算法来实现分布式存储. ...

随机推荐

  1. iOS 开发之 RunLoop 详解

    1)什么是 Runloop ? 1.字面上是运行循环,内部就是 do-while 循环,在这个循环内不断地处理各种任务. 2.一个线程对应一个 Runloop ,主线程的 RunLoop 默认是开启的 ...

  2. 【译】索引进阶(十七): SQL SERVER索引最佳实践

    [译注:此文为翻译,由于本人水平所限,疏漏在所难免,欢迎探讨指正] 原文链接:传送门. 在本章我们给出一些建议:贯穿本系列我们提取出了十四条基本指南,这些基本的指南将会帮助你为你的数据库创建最佳的索引 ...

  3. 无法获得锁/var/lib/dpkg/lock - open(11.资源暂时不可用)

    E:无法获得锁/var/lib/dpkg/lock  - open(11.资源暂时不可用) E:无法锁定资源目录(/var/lib/dpkg)是否有其他进程正占用它? 解决方案: sudo rm /v ...

  4. js中字符串转json对象时报错: Uncaught SyntaxError: Unexpected token s in JSON at position 2

    解决方法: js中获取jsp的返回值 var json='${channels}' var channels = JSON.parse(json);就报上面的错. json的值最终会转成这种json格 ...

  5. Cosmetic Sprayer Structure Anatomy

    What shape of spray is sprayed by the cosmetic spray pump head?     Plastic Sprayers Manufacturer   ...

  6. SpringData学习笔记一

    Spring Data : 介绍: Spring 的一个子项目.用于简化数据库访问,支持NoSQL 和 关系数据存储.其主要目标是使数据库的访问变得方便快捷. SpringData 项目所支持 NoS ...

  7. python 基础之深浅拷贝

    深浅拷贝 s=[[1,2],'fgfgf','cx'] s3=s.copy() print(s) print(s3) 测试 D:\python\python.exe D:/untitled/dir/f ...

  8. android.view.WindowManager$BadTokenException 崩掉

    问题: 以前的项目,今天打开运行,Activity刚打开的时候,点开一个弹窗是好的,但是再点到另一个界面的时候,返回,再点弹窗就崩了. 解决: 网上查了一下,发现出现这个问题的还特别多,大体如下: 1 ...

  9. Linux centosVMware Apache 配置防盗链、访问控制Directory、访问控制FilesMatch

    一.配置防盗链 通过限制referer来实现防盗链的功能 配置文件增加如下内容 vim /usr/local/apache2.4/conf/extra/httpd-vhosts.conf //改为如下 ...

  10. HTML元素和测试用例的简要介绍

    HTML和CSS的基本语法就不出教程,线下自己看电子书即可 HTML元素 标签 内容 属性 标签+内容+属性 <html> <head> <title>我的主页&l ...