PHP一致性hash分布式算法封装类定义与用法示例


Posted in PHP onAugust 04, 2018

本文实例讲述了PHP一致性hash分布式算法封装类定义与用法。分享给大家供大家参考,具体如下:

一、无虚拟节点实现

<?php
/**
 * 一致性hash分布式算法
 * @param $key
 * @return int
 * 实现步骤
 * 1.先将0~ 是32位最大带符号整数(0x7FFFFFFF) 想象成一个闭环
 * 2.将服务器列表通过hash算法分布在 圆环之中
 * 3.将key值也分布在圆环之中
 * 4.通过_isSorted判断服务器是否需要进行倒序排序 排序后遍历服务器 找到最近的服务器 返回
 * hash算法是不保证平衡的 为了尽量保证平衡性 我们应该加入虚拟节点数 将一个服务器节点虚拟化成为多个 较大程度上保证了平衡性
 */
class FlexiHash{
  private $_serverList = array();
  private $_isSorted = false;
  private $_virtual_node_num = 20;//虚拟节点数 服务器越少 增加的虚拟节点数应该越多
  //通过hash算法返回一个整数值
  protected function myHash($key){
    $md5 = substr(md5($key),0,8);
    $seed = 31; //种子值
    $hash=0;
    for($i=0;$i<8;$i++){
      $hash = $hash*$seed+ord($md5{$i}); //ord 返回ascii值
      $i++;
    }
    return $hash&0x7FFFFFFF; //0x7FFFFFFF表示最大值
  }
  //添加服务器
  function addServer($server){
    $hash =$this->myHash($server. '#1');
    if(!isset($this->_serverList[$hash])) {
      for ($i = 1; $i <= $this->_virtual_node_num; $i++) {
        $hash = $this->myHash($server . '#' . $i);
        $this->_serverList[$hash] = $server;
      }
    }
    $this->_isSorted = false;
    return true;
  }
  //删除服务器
  function removeServer($server){
    for ($i = 1; $i <= $this->_virtual_node_num; $i++) {
      $hash = $this->myHash($server . '#' . $i);
      unset($this->_serverList[$hash]);
    }
    $this->_isSorted = false;
    return true;
  }
  //获取服务器
  function lookup($key){
    $hash =$this->myHash($key);
    if(!$this->_isSorted){
      krsort($this->_serverList,SORT_NUMERIC);
      $this->_isSorted = true;
    }
    foreach($this->_serverList as $pos=>$server){
      if($hash >= $pos) return $server;
    }
    return end($this->_serverList);
  }
  public function getServerList(){
    krsort($this->_serverList,SORT_NUMERIC);
    return $this->_serverList;
  }
}
//demo test
$hserver = new FlexiHash();
//添加服务器
$hserver->addServer('192.168.1.1');
$hserver->addServer('192.168.1.2');
$hserver->addServer('192.168.1.3');
$hserver->addServer('192.168.1.4');
$hserver->addServer('192.168.1.5');
$key1='Key1111';
$key2='Key2222';
$key2='Key3333';
$key2='Key4444';
$key2='Key5555';
$key2='Key6666';
echo "save key1 in server: ".$hserver->lookup($key1).PHP_EOL;
echo "save key2 in server: ".$hserver->lookup($key2).PHP_EOL;
echo "save key1 in server: ".$hserver->lookup($key3).PHP_EOL;
echo "save key2 in server: ".$hserver->lookup($key4).PHP_EOL;
echo "save key1 in server: ".$hserver->lookup($key5).PHP_EOL;
echo "save key2 in server: ".$hserver->lookup($key6).PHP_EOL;
echo "================================================".PHP_EOL;
//移除服务器 key值将自动转义到下一台服务器
$hserver->removeServer('192.168.1.4');
echo "save key1 in server: ".$hserver->lookup($key1).PHP_EOL;
echo "save key2 in server: ".$hserver->lookup($key2).PHP_EOL;
echo "save key1 in server: ".$hserver->lookup($key3).PHP_EOL;
echo "save key2 in server: ".$hserver->lookup($key4).PHP_EOL;
echo "save key1 in server: ".$hserver->lookup($key5).PHP_EOL;
echo "save key2 in server: ".$hserver->lookup($key6).PHP_EOL;
echo "================================================".PHP_EOL;
//恢复故障服务器 key值将恢复原来服务器
$hserver->addServer('192.168.1.4');
echo "save key1 in server: ".$hserver->lookup($key1).PHP_EOL;
echo "save key2 in server: ".$hserver->lookup($key2).PHP_EOL;
echo "save key1 in server: ".$hserver->lookup($key3).PHP_EOL;
echo "save key2 in server: ".$hserver->lookup($key4).PHP_EOL;
echo "save key1 in server: ".$hserver->lookup($key5).PHP_EOL;
echo "save key2 in server: ".$hserver->lookup($key6).PHP_EOL;

二、运行结果:

save key1 in server: 192.168.1.4
save key2 in server: 192.168.1.4
save key1 in server: 192.168.1.3
save key2 in server: 192.168.1.3
save key1 in server: 192.168.1.3
save key2 in server: 192.168.1.3
================================================
save key1 in server: 192.168.1.2
save key2 in server: 192.168.1.5
save key1 in server: 192.168.1.3
save key2 in server: 192.168.1.3
save key1 in server: 192.168.1.3
save key2 in server: 192.168.1.3
================================================
save key1 in server: 192.168.1.4
save key2 in server: 192.168.1.4
save key1 in server: 192.168.1.3
save key2 in server: 192.168.1.3
save key1 in server: 192.168.1.3
save key2 in server: 192.168.1.3

PHP 相关文章推荐
一周学会PHP(视频)Http下载
Dec 12 PHP
php 日期时间处理函数小结
Dec 18 PHP
php jq jquery getJSON跨域提交数据完整版
Sep 13 PHP
10个简化PHP开发的工具
Dec 25 PHP
php动态生成版权所有信息的方法
Mar 24 PHP
浅谈PHP中其他类型转化为Bool类型
Mar 28 PHP
Ubuntu server 11.04安装memcache及php使用memcache来存储session的方法
May 31 PHP
php解析xml 的四种简单方法(附实例)
Jul 11 PHP
PHP中$GLOBALS['HTTP_RAW_POST_DATA']和$_POST的区别分析
Jul 03 PHP
详解php curl带有csrf-token验证模拟提交方法
Apr 18 PHP
PHP实现redis限制单ip、单用户的访问次数功能示例
Jun 16 PHP
常见的5个PHP编码小陋习以及优化实例讲解
Feb 27 PHP
PHP实现的函数重载功能示例
Aug 03 #PHP
thinkPHP5框架导出Excel文件简单操作示例
Aug 03 #PHP
PHP命名空间namespace及use的简单用法分析
Aug 03 #PHP
PHP后台实现微信小程序登录
Aug 03 #PHP
thinkPHP5框架闭包函数与子查询传参用法示例
Aug 02 #PHP
PHP实现的AES加密、解密封装类与用法示例
Aug 02 #PHP
lnmp安装多版本PHP共存的方法详解
Aug 02 #PHP
You might like
php获取网页中图片、DIV内容的简单方法
2014/06/19 PHP
PHP实现加强版加密解密类实例
2015/07/29 PHP
PHP实现基于图的深度优先遍历输出1,2,3...n的全排列功能
2017/11/10 PHP
WordPress免插件实现面包屑导航的示例代码
2020/08/20 PHP
javascript 兼容鼠标滚轮事件
2009/04/07 Javascript
文本有关的样式和jQuery求对象的高宽问题分别说明
2013/08/30 Javascript
window.print打印指定div实例代码
2013/12/13 Javascript
js监听鼠标点击和键盘点击事件并自动跳转页面
2014/09/24 Javascript
jquery分析文本里url或邮件地址为真实链接的方法
2015/06/20 Javascript
浅析JavaScript 调试方法和技巧
2015/10/22 Javascript
在Web项目中引入Jquery插件报错的完美解决方案(图解)
2016/09/19 Javascript
AngularJs1.x自定义指令独立作用域的函数传入参数方法
2018/10/09 Javascript
Easyui 关闭jquery-easui tab标签页前触发事件的解决方法
2019/04/28 jQuery
js基础之事件捕获与冒泡原理
2019/10/09 Javascript
JavaScript函数IIFE使用详解
2019/10/21 Javascript
element-ui 文件上传修改文件名的方法示例
2019/11/05 Javascript
原生JS与CSS实现软件卸载对话框功能
2019/12/05 Javascript
[01:25]DOTA2自定义游戏灵园鬼域等你踏足
2015/10/30 DOTA
[02:46]解说DC:感谢430陪伴我们的DOTA2国际邀请赛岁月
2016/06/29 DOTA
Python程序退出方式小结
2017/12/09 Python
pycharm使用matplotlib.pyplot不显示图形的解决方法
2018/10/28 Python
浅谈python的深浅拷贝以及fromkeys的用法
2019/03/08 Python
Python自动化完成tb喵币任务的操作方法
2019/10/30 Python
pycharm双击无响应(打不开问题解决办法)
2020/01/10 Python
django 扩展user用户字段inlines方式
2020/03/30 Python
h5实现获取用户地理定位的实例代码
2017/07/17 HTML / CSS
洛杉矶时尚女装系列:J.ING US
2019/03/17 全球购物
Weblogic的布署方式
2013/08/23 面试题
介绍一下.NET构架下remoting和webservice
2014/05/08 面试题
工作中的自我评价如何写好
2013/10/28 职场文书
创建服务型党组织实施方案
2014/02/25 职场文书
李培根演讲稿
2014/05/22 职场文书
放假通知
2015/04/14 职场文书
MySQL 发生同步延迟时Seconds_Behind_Master还为0的原因
2021/06/21 MySQL
一篇文章弄清楚Ajax请求的五个步骤
2022/03/17 Javascript
动漫APP软件排行榜前十名,半次元上榜,第一款由腾讯公司推出
2022/03/18 杂记