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 相关文章推荐
PHP4中实现动态代理
Oct 09 PHP
smarty section简介与用法分析
Oct 03 PHP
yii框架源码分析之创建controller代码
Jun 28 PHP
给初学者的30条PHP最佳实践(荒野无灯)
Aug 02 PHP
解析link_mysql的php版
Jun 30 PHP
详解PHP编码转换函数应用技巧
Oct 22 PHP
php获取当前月与上个月月初及月末时间戳的方法
Dec 05 PHP
PHP实现截取中文字符串不出现?号的解决方法
Dec 29 PHP
PHP实现百度人脸识别
May 06 PHP
Laravel 添加多语言提示信息的方法
Sep 29 PHP
Laravel 错误提示本地化的实现
Oct 22 PHP
PHP实现获取文件mime类型多种方法解析
May 28 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中批量替换文件名的实现代码
2011/07/20 PHP
php中jQuery插件autocomplate的简单使用笔记
2012/06/14 PHP
完美实现wordpress禁止文章修订和自动保存的方法
2014/11/03 PHP
PHP PDOStatement::setAttribute讲解
2019/02/01 PHP
ExtJS 2.2.1的grid控件在ie6中的显示问题
2009/05/04 Javascript
在JavaScript中使用timer示例
2014/05/08 Javascript
JavaScript版的TwoQueues缓存模型
2014/12/29 Javascript
JavaScript获取指定元素位置的方法
2015/04/08 Javascript
JS组件Bootstrap实现下拉菜单效果代码
2016/04/26 Javascript
纯js实现的积木(div层)拖动功能示例
2017/07/19 Javascript
Kindeditor单独调用多图上传实例
2017/07/31 Javascript
iframe与主框架跨域相互访问实现方法
2017/09/14 Javascript
微信小程序实现的点击按钮 弹出底部上拉菜单功能示例
2018/12/20 Javascript
Vue-CLI项目中路由传参的方式详解
2019/09/01 Javascript
layer页面跳转,获取html子节点元素的值方法
2019/09/27 Javascript
JavaScript事件冒泡机制原理实例解析
2020/01/14 Javascript
Python程序设计入门(5)类的使用简介
2014/06/16 Python
Python合并多个装饰器小技巧
2015/04/28 Python
详谈python http长连接客户端
2017/06/12 Python
Python+Socket实现基于TCP协议的客户与服务端中文自动回复聊天功能示例
2017/08/31 Python
Python人脸识别初探
2017/12/21 Python
python 不以科学计数法输出的方法
2018/07/16 Python
纽约香氛品牌:NEST Fragrance
2018/10/15 全球购物
皇家阿尔伯特瓷器美国官网:Royal Albert美国
2020/02/16 全球购物
信息管理专业推荐信
2013/10/29 职场文书
学院书画协会部门岗位职责
2013/12/01 职场文书
高三生物教学反思
2014/01/25 职场文书
工作过失检讨书
2014/02/23 职场文书
经典安踏广告词
2014/03/21 职场文书
顶岗实习协议书
2015/01/29 职场文书
管理人员岗位职责
2015/02/14 职场文书
信访维稳承诺书
2015/05/04 职场文书
文案策划岗位个人自我评价(范文)
2019/08/08 职场文书
研究生学习计划书应该怎么写?
2019/09/10 职场文书
Python 制作自动化翻译工具
2021/04/25 Python
MySQL 如何分析查询性能
2021/05/12 MySQL