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具体实现代码
Oct 12 PHP
php学习之数据类型之间的转换代码
May 29 PHP
功能强大的PHP图片处理类(水印、透明度、旋转)
Oct 21 PHP
教你php如何实现验证码
Jan 20 PHP
PHP计算日期相差天数实例分析
Feb 23 PHP
php生成图片验证码的方法
Apr 15 PHP
使用ThinkPHP的自动完成实现无限级分类实例详解
Sep 02 PHP
PHP会员找回密码功能的简单实现
Sep 05 PHP
php将print_r处理后的数据还原为原始数组的解决方法
Nov 02 PHP
PHP Mysqli 常用代码集合
Nov 12 PHP
10个值得深思的PHP面试题
Nov 14 PHP
Yii2 批量插入、更新数据实例
Mar 15 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函数
2006/12/06 PHP
php array_values 返回数组的值实例详解
2016/11/17 PHP
因str_replace导致的注入问题总结
2019/08/08 PHP
学习jquery必备 api中英文对照的chm手册 下载
2007/05/03 Javascript
JQuery 网站换肤功能实现代码
2009/11/02 Javascript
JavaScript 继承机制的实现(待续)
2010/05/18 Javascript
JS上传图片前的限制包括(jpg jpg gif及大小高宽)等
2012/12/19 Javascript
select标记美化--JS式插件、后期加载
2013/04/01 Javascript
javascript trim函数在IE下不能用的解决方法
2014/09/12 Javascript
基于jquery实现省市联动特效
2015/12/17 Javascript
js实现瀑布流的三种方式比较
2020/06/28 Javascript
jQuery数据类型小结(14个)
2016/01/08 Javascript
javascript加载xml 并解析各节点的值(实现方法)
2016/10/12 Javascript
Bootstrap Table使用整理(三)
2017/06/09 Javascript
AngularJS ionic手势事件的使用总结
2017/08/09 Javascript
javaScript实现游戏倒计时功能
2018/11/17 Javascript
nodejs的安装使用与npm的介绍
2019/09/11 NodeJs
Vue.extend 编程式插入组件的实现
2019/11/18 Javascript
详解Node.JS模块 process
2020/08/31 Javascript
JavaScript用document.write()输出换行的示例代码
2020/11/26 Javascript
Python中的测试模块unittest和doctest的使用教程
2015/04/14 Python
Python使用PIL模块生成随机验证码
2017/11/21 Python
使用Python机器学习降低静态日志噪声
2018/09/29 Python
纯CSS3实现扇形动画菜单(简化版)实例源码
2017/01/17 HTML / CSS
HTML5调用手机摄像头拍照的实现思路及代码
2014/06/15 HTML / CSS
Skyscanner香港:机票比价, 平机票和廉价航空机票预订
2020/02/07 全球购物
《故都的秋》教学反思
2014/04/15 职场文书
国旗下的演讲稿
2014/05/08 职场文书
公司投资建议书
2014/05/16 职场文书
毕业生工作求职信
2014/06/30 职场文书
联村联户简报
2015/07/21 职场文书
MySQL系列之十一 日志记录
2021/07/02 MySQL
javascript的setTimeout()使用方法总结
2021/11/20 Javascript
剧场版《转生恶役只好拔除破灭旗标》公开最新视觉图 2023年上映
2022/04/02 日漫
springboot用户数据修改的详细实现
2022/04/06 Java/Android
Java8利用Stream对列表进行去除重复的方法详解
2022/04/14 Java/Android