如何用PHP实现分布算法之一致性哈希算法


Posted in PHP onMay 26, 2021

传统算法缺陷

对于服务器分布,我们要考虑的东西有如下三点:数据平均分布,查找定位准确,降低宕机影响。

传统算法一般是将数据的键用算法映射出数字,对其用服务器数量取模,并根据结果选择要存储的服务器。其能达到数据平均分布和查找定位准确的要求,并且优点是算法简单,存取时的计算量都比较小(在数据非常大时才会明显)。

但其有一个致命缺点,即一个服务器宕机后的影响很大,我们可以推算一下一台服务器宕机后的影响:

  • 原有数据大部分丢失:服务器数量减少一台,取模数减1导致取模值错乱,如果以前有N台服务器,那么宕机后数据只有1/(n*(n-1))的数据能够被准确查找到。
  • 负载无法均衡导致集体宕机:如果没有及时处理宕机的服务器,那么他的存储任务将会被顺序积累给它的下一个服务器,那么下一个服务器也会很快被压致宕机,如此一来,服务器组很快会集体宕机。

算法思想

一致性哈希算法是使用一定的哈希算法,将大量的数据平均映射到不同的存储目标上,在保证其查找准确性的同时,还要考虑其中一个存储目标失效时,其他存储目标对其责任存储内容的负载均衡。

一致性哈希算法的实现思想不难理解,如图:

如何用PHP实现分布算法之一致性哈希算法

1.用一定的哈希算法(哈希函数等)将一组服务器的多个(数目自己设定)节点随机映射分散到0-232之间,由于其随机分布,保证了其数据平均分布的特点;

2.用同一算法计算要存储数据的键,根据服务器节点确定其存储的服务器结点,由于每次用同一算法计算,所以得出的结果是相同的,使其查找定位准确;

3.查找数据时,再次用同一算法计算键,并查找服务器的数据结点;

4.如果有一个服务器宕机,消除其服务器结点,并将数据放在下一个结点上,由于随机节点位置的随机性,所以数据被其他服务器平均负载,也就降低了宕机影响。

需要注意的是,这个环形空间只是一个虚拟空间,只是表示了服务器存储的范围和数据的落点,在进行存储时,我们还要通过查找到的落点,将数据放入对应的服务器进行查改。

算法实现

编程语言我们使用PHP来实现一致性哈希算法:

我们主要用到以下函数:

int crc32 ( string $str )
生成 str 的 32 位循环冗余校验码多项式。这通常用于检查传输的数据是否完整。

string sprintf ( string $format [, mixed $args [, mixed $... ]] )
通过传入的格式产生字符串的特定格式形态。

实现如下:

class Consistance
{
    protected $num=24;          //设定每一个服务器的节点数,数量越多,宕机时服务器负载就会分布得越平均,但也增大数据查找消耗。
    protected $nodes=array();   //当前服务器组的结点列表。

    //计算一个数据的哈希值,用以确定位置
    public function make_hash($data)
    {
        return sprintf('%u',crc32($data));
    }

    //遍历当前服务器组的节点列表,确定需要存储/查找的服务器
    public function set_loc($data)
    {
        $loc=self::make_hash($data);
        foreach ($this->nodes as $key => $val)
        {
            if($loc<=$key)
            {
                return $val;
            }
        }
    }

    //添加一个服务器,将其结点添加到服务器组的节点列表内。
    public function add_host($host)
    {
        for($i=0;$i<$this->num;$i++)
        {
            $key=sprintf('%u',crc32($host.'_'.$i));
            $this->nodes[$key]=$host;   
        }
        ksort($this->nodes);        //对结点排序,这样便于查找。
    }

    //删除一个服务器,并将其对应节点从服务器组的节点列表内移除。
    public function remove_host($host)
    {
        for($i=0;$i<$this->num;$i++)
        {
            $key=sprintf('%u',crc32($host.'_'.$i));
            unset($this->nodes[$key]);
        }
    }
}

我们用以下代码进行测试:

如何用PHP实现分布算法之一致性哈希算法

结果如下:

如何用PHP实现分布算法之一致性哈希算法

总结

算法的实现到此,我们还可以对算法进行优化,如在服务器数量和每个服务器节点数都很多的情况下,对查找结点的过程进行优化,因为排序好的,可以用二分法进行查找,加快查询效率,这些,仁智各见吧。

另外,虽然nginx服务器有一致性算法的插件,memcache和redis也都有相应的插件,MySQL的中间件有相应的集成,但是了解一致性哈希算法也很有意义。而且,我们也可以对其灵活使用,如对文件等进行分布式管理等等。

以上就是如何用PHP实现分布算法之一致性哈希算法的详细内容,更多关于用PHP实现分布算法之一致性哈希算法的资料请关注三水点靠木其它相关文章!

PHP 相关文章推荐
小偷PHP+Html+缓存
Nov 25 PHP
Apache2 httpd.conf 中文版
Dec 06 PHP
apache2.2.4+mysql5.0.77+php5.2.8安装精简
Apr 29 PHP
PHP教程 基本语法
Oct 23 PHP
解析Win7 XAMPP apache无法启动的问题
Jun 26 PHP
CI映射(加载)数据到view层的方法
Mar 28 PHP
Yii2 加载css、js 载静态资源的方法
Mar 10 PHP
ThinkPHP3.1.x修改成功与失败跳转页面的方法
Sep 29 PHP
PHP面向对象程序设计(OOP)之方法重写(override)操作示例
Dec 21 PHP
phpstudy后门rce批量利用脚本的实现
Dec 12 PHP
PHP const定义常量及global定义全局常量实例解析
May 28 PHP
php中yar框架实例用法讲解
Dec 27 PHP
如何用PHP实现多线程编程
May 26 #PHP
如何用PHP websocket实现网页实时聊天
详解PHP用mb_string处理windows中文字符
May 26 #PHP
详解PHP服务器如何在有限的资源里最大提升并发能力
详解PHP设计模式之依赖注入模式
阿里云服务器搭建Php+Apache运行环境的详细过程
php+laravel 扫码二维码签到功能
You might like
php仿ZOL分页类代码
2008/10/02 PHP
关于Iframe如何跨域访问Cookie和Session的解决方法
2013/04/15 PHP
PHP的fsockopen、pfsockopen函数被主机商禁用的解决办法
2014/07/08 PHP
ECSHOP在PHP5.5及高版本上报错的解决方法
2015/08/31 PHP
PHP文件与目录操作示例
2016/12/24 PHP
总结PHP代码规范、流程规范、git规范
2018/06/18 PHP
通过PHP的Wrapper无缝迁移原有项目到新服务的实现方法
2020/04/02 PHP
深入认识JavaScript中的函数
2007/01/22 Javascript
让JavaScript 轻松支持函数重载 (Part 1 - 设计)
2009/08/04 Javascript
JSON 数据格式介绍
2012/01/13 Javascript
JavaScript的继承的封装介绍
2013/10/15 Javascript
js将json格式的对象拼接成复杂的url参数方法
2016/05/25 Javascript
javascript弹出带文字信息的提示框效果
2016/07/19 Javascript
js 自带的 map() 方法全面了解
2016/08/16 Javascript
js仿小米官网图片轮播特效
2016/09/29 Javascript
JS动画实现回调地狱promise的实例代码详解
2018/11/08 Javascript
vue+web端仿微信网页版聊天室功能
2019/04/30 Javascript
[54:27]TNC vs Serenity 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
Python中函数的参数传递与可变长参数介绍
2015/06/30 Python
python SSH模块登录,远程机执行shell命令实例解析
2018/01/12 Python
Django框架实现的简单分页功能示例
2018/12/04 Python
浅谈python中get pass用法
2019/03/19 Python
Python中os模块功能与用法详解
2020/02/26 Python
解决pytorch多GPU训练保存的模型,在单GPU环境下加载出错问题
2020/06/23 Python
基于Python和C++实现删除链表的节点
2020/07/06 Python
HTML5资源预加载(Link prefetch)详细介绍(给你的网页加速)
2014/05/07 HTML / CSS
html5 canvas合成海报所遇问题及解决方案总结
2017/08/03 HTML / CSS
印度购买眼镜和太阳镜网站:Coolwinks
2018/09/26 全球购物
说出数据连接池的工作机制是什么?
2013/04/19 面试题
三维科技面试题
2013/07/27 面试题
what is the difference between ext2 and ext3
2013/11/03 面试题
王兆力在市委党的群众路线教育实践活动总结大会上的讲话稿
2014/10/25 职场文书
学习新党章心得体会2016
2016/01/15 职场文书
Java内存模型之happens-before概念详解
2021/06/13 Java/Android
原生JavaScript实现简单五子棋游戏
2021/06/28 Javascript
最新最全的手机号验证正则表达式
2022/02/24 Javascript