文档章节

PHP一致性hash代码

我爱吃炒鸡
 我爱吃炒鸡
发布于 02/22 03:42
字数 759
阅读 173
收藏 0

[TOC]

PHP实现一致性hash

bash命令

因为下面PHP代码的模拟用户用的是随机数,所以统计结果达不到绝对的均衡.

php ./hash.php | sort | uniq -c | sort

PHP代码

这是之前学的时候留下来的测试代码,原理方面就不赘述了.

<?php


/**
 * @class  ConsistentHash
 * @desc   无符号的一致性hash
 * @author liuhao
 */
class ConsistentHash
{
    protected $nodeList = []; //服务器列表
    protected $virtualNodeSite = []; //虚拟节点的位置
    protected $virtualNodeCount = 20;  //每个节点对应20个虚节点

    /**
     * @desc   在服务器列表中, 为用户匹配合适的服务器
     * @action getNodeAction
     * @param  string  $key  键名
     * @return string    服务器IP地址
     * @author liuhao
     */
    public function getNode($key)
    {
        //获取当前下标的hash值
        $keyHash = $this->crc32Hash($key);
        //先把hash环上上最小的一个节点临时当作是我们需要的节点
        $resultHost = current($this->virtualNodeSite);
        foreach ($this->virtualNodeSite as $nodeHash => $host) {
            if ($keyHash <= $nodeHash) {
                $resultHost = $host;
                break;
            }
        }
        //重置圆环的指针为第一个
        reset($this->virtualNodeSite);

        return $resultHost;
    }

    /**
     * @desc   将字符串转换成32位无符号整数hash值
     * @action crc32HashAction
     * @param  string  $str
     * @return string
     * @author liuhao
     */
    protected function crc32Hash($str)
    {
        //由于 PHP 的整数是带符号的,所以在 32 位系统上许多 crc32 校验码将返回负整数。 尽管在 64 位上所有 crc32() 的结果将都是正整数。
        //因此你需要使用 sprintf() 或 printf() 的“%u”格式符来获取表示无符号 crc32 校验码的字符串。
        $str = crc32(md5($str));
        return sprintf('%u', $str);
    }

    /**
     * @desc   向服务器列表,添加一个新的服务器
     * @action addNodeAction
     * @param  string  $host  服务器IP地址
     * @return bool
     * @author liuhao
     */
    public function addNode($host)
    {
        if (!isset($this->nodeList[$host])) {
            for ($i = 0; $i < $this->virtualNodeCount; $i++) {
                $hostHash                         = $this->crc32Hash($host.'-'.$i);
                $this->virtualNodeSite[$hostHash] = $host;
                $this->nodeList[$host][]          = $hostHash;
            }
            ksort($this->virtualNodeSite, SORT_NUMERIC);
        }
        return true;
    }

    /**
     * @desc    循环所有的虚节点,删除值为该服务器地址的虚节点
     * @action  delNodeAction
     * @param  string  $host
     * @return bool
     * @author  liuhao
     */
    public function delNode($host)
    {
        if (isset($this->nodeList[$host])) {
            //删除对应虚节点
            foreach ($this->nodeList[$host] as $pos) {
                unset($this->virtualNodeSite[$pos]);
            }
            //删除对应服务器
            unset($this->nodeList[$host]);
        }
        return true;
    }
}

//节点服务器列表
$ipArr = [
    "192.168.1.100",
    "192.168.1.102",
    "192.168.1.103",
    "192.168.1.104",
    "192.168.1.105",
    "192.168.1.106",
    "192.168.1.107",
    "192.168.1.108",
    "192.168.1.109",
    "192.168.1.110",
    "192.168.1.111",
    "192.168.1.112",
    "192.168.1.113",
    "192.168.1.114",
    "192.168.1.115",
    "192.168.1.116",
    "192.168.1.117",
    "192.168.1.118",
    "192.168.1.119",
    "192.168.1.120",
];

$hashServer = new ConsistentHash();
//添加节点
foreach ($ipArr as $key => $value) {
    $hashServer->addNode($value);
//    echo "节点服务器{$key}: ======> {$value}".PHP_EOL;
}
echo PHP_EOL;

//模拟访问函数
$fakeVisit = function () use (&$hashServer) {
//用户访问总次数
    $visitsTotal = 100;
    for ($i = 0; $i < $visitsTotal; $i++) {
        //假定5个用户随机访问
        $rand = mt_rand(0, 5);
        echo "用户{$rand} 连接的节点是: ".$hashServer->getNode($rand).PHP_EOL;
    }

};

//模拟访问
$fakeVisit();

exit;
//随机删除一台服务器
$randIPFunc = function () use ($ipArr) {
    return $ip = $ipArr[array_rand($ipArr, 1)];
};

echo PHP_EOL;
$randIP = $randIPFunc();
echo "用户删除的节点服务器是:{$randIP}".PHP_EOL;
echo PHP_EOL;
$hashServer->delNode($randIP);


//模拟访问
$fakeVisit();


echo PHP_EOL;
$randIP = $randIPFunc();
echo "用户删除的节点服务器是:{$randIP}".PHP_EOL;
echo PHP_EOL;
$hashServer->delNode($randIP);

//模拟访问
$fakeVisit();

© 著作权归作者所有

我爱吃炒鸡

我爱吃炒鸡

粉丝 12
博文 169
码字总数 520574
作品 0
东城
高级程序员
私信 提问
加载中

评论(0)

nginx+PHP+memcached+MySQL+ip-hash做memcached集群

1、nginx与memcached整合 #安装memcached支持的事务库libevent wget https://github.com/libevent/libevent/releases/download/release-2.0.22-stable/libevent-2.0.22-stable.tar.gztar zxf......

80后小菜鸟
2017/09/01
0
0
【转载】memcache分布式 [一致性hash算法] 的php实现

最近在看一些分布式方面的文章,所以就用php实现一致性hash来练练手,以前一般用的是最原始的hash取模做分布式,当生产过程中添加或删除一台memcache都会造成数据的全部失效,一致性hash就是...

hengfeng_su
2015/04/01
186
0
哈希分布与一致性哈希算法简介

前言 在我们的日常web应用开发当中memcached可以算作是当今的标准开发配置了。相信memcache的基本原理大家也都了解过了,memcache虽然是分布式的应用服务,但分布的原则是由client端的api来决...

晨曦之光
2012/03/09
266
0
memcache一致性hash的php实现方法

memcache一致性hash的php实现方法 本文实例讲述了memcache一致性hash的php实现方法。分享给大家供大家参考。具体如下: 最近在看一些分布式方面的文章,所以就用php实现一致性hash来练练手,...

开元中国2015
2015/04/20
82
0
通过PHP的hash冲突漏洞进行DDoS攻击的解决办法

通过PHP的hash冲突漏洞进行DDoS攻击的解决办法 最近各语言爆hash碰撞漏洞。包含php,ruby,python,java各个语言。Microsoft的.net也受影响。 hash碰撞原理: Hash,简单来讲,是一种将任意长度的...

keengo
2012/01/07
416
0

没有更多内容

加载失败,请刷新页面

加载更多

PHP中Session ID的实现原理

Session 的工作机制是:为每个访问者创建一个唯一的 id (UID),并基于这个 UID 来存储变量。UID 存储在 cookie 中,亦或通过 URL 进行传导。 PHPSESSIONID的生产算法原理如下: hash_func = ...

php开源社区
13分钟前
9
0
MySQL设置允许用户远程登录

项目中需要连接虚拟机上面的MySQL数据库,但是总是出错,怀疑本机是否有连接远程数据库的权限。 执行命令: mysql> use mysql;mysql> select host,user from user; 查看结果是不是root用...

imzchloe
21分钟前
13
0
TI达芬奇系列TMS320DM8148浮点DSP C674x + ARM Cortex-A8USB OTG/USB HUB接口、SATA接口(仅DM8148)V

处理器 DM8148 TI TMS320DM8148是一款高性能嵌入式32位工业级ARM Cortex-A8+DSP C674x处理器。拥有多种工业接口资源,以下是DM8148 CPU资源框图: USB OTG/USB HUB接口 CON13、CON14为Micro...

Tronlong创龙
22分钟前
9
0
一个对二维数组进行多字段多顺序排序的方法

1,代码 <?php/** * 对二维数组依次按照排序规则数组指定的字段和顺序进行排序,在有相同的情况下按下一个字段和顺序进行排序 * @param array $arr 待排序的数组 * @param array $...

vinci321
22分钟前
3
0
2019阿里技术专家面试题大汇总(内含答案)

为帮助开发者们提升面试技能、有机会入职阿里,云栖社区特别制作了这个专辑——阿里巴巴资深技术专家们结合多年的工作、面试经验总结提炼而成的面试真题这一次整体放出。并通过这些笔试真题开...

白楠楠
23分钟前
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部