【转载】memcache分布式 [一致性hash算法] 的php实现

最近在看一些分布式方面的文章,所以就用php实现一致性hash来练练手,以前一般用的是最原始的hash取模做分布式,当生产过程中添加或删除一台memcache都会造成数据的全部失效,一致性hash就是为了解决这个问题,把失效数据降到最低,相关资料可以google一下!

php实现效率有一定的缺失,如果要高效率,还是写扩展比较好
经测试,5个memcache,每个memcache生成100个虚拟节点,set加get1000次,与单个memcache直接set加get慢5倍,所以效率一般,有待优化!
实现过程:

  • memcache的配置 ip+端口+虚拟节点序列号 做hash,使用的是crc32,形成一个闭环。
  • 对要操作的key进行crc32
  • 二分法在虚拟节点环中查找最近的一个虚拟节点
  • 从虚拟节点中提取真实的memcache ip和端口,做单例连接
<?php
/**
* 一致性哈希memcache分布式,采用的是虚拟节点的方式解决分布均匀性问题,查找节点采用二分法快速查找
* the last known user to change this file in the repository  <$LastChangedBy: nash.xiong [        DISCUZ_CODE_0        ]gt;
* @author nash.xiong <[email protected]>
* @copyright Copyright &copy; 2003-2012 phpd.cn
* @license 
*/
class memcacheHashMap {

        private $_node = array();
        private $_nodeData = array();
        private $_keyNode = 0;
        private $_memcache = null;
        
        //每个物理服务器生成虚拟节点个数 [注:节点数越多,cache分布的均匀性越好,同时set get操作时,也更耗资源,10台物理服务器,采用200较为合理]
        private $_virtualNodeNum = 200; 
        
        private function __construct() {
                /* 放入配置文件 */
                $config = array(
                                                ‘127.0.0.1:11211‘,
                                                ‘127.0.0.1:11212‘,
                                                ‘127.0.0.1:11213‘,
                                                ‘127.0.0.1:11214‘,
                                                ‘127.0.0.1:11215‘
                                        );
                                        
                if (!$config) throw new Exception(‘Cache config NULL‘);
                foreach ($config as $key => $value) {
                        for ($i = 0; $i < $this->_virtualNodeNum; $i++) {
                                $this->_node[sprintf("%u", crc32($value . ‘_‘ . $i))] = $value . ‘_‘ . $i;
                        }
                }
                ksort($this->_node);
        }

        private function __clone(){}
        
        /**
         * 单例,保证只有一个实例
         */
        static public function getInstance() {
                static $memcacheObj = null;
                if (!is_object($memcacheObj)) {
                        $memcacheObj = new self();
                }
                return $memcacheObj;
        }
        
        /**
         * 根据key做一致性hash后连接到一台物理memcache服务器
         * @param string $key
         */
        private function _connectMemcache($key) {
                $this->_nodeData = array_keys($this->_node);
                $this->_keyNode = sprintf("%u", crc32($key));
                $nodeKey = $this->_findServerNode();
                //如果超出环,从头再用二分法查找一个最近的,然后环的头尾做判断,取最接近的节点
                if ($this->_keyNode > end($this->_nodeData)) {
                        $this->_keyNode -= end($this->_nodeData);
                        $nodeKey2 = $this->_findServerNode();
                        if (abs($nodeKey2 - $this->_keyNode) < abs($nodeKey - $this->_keyNode))  $nodeKey = $nodeKey2;
                }
                var_dump($this->_node[$nodeKey]);
                list($config, $num) = explode(‘_‘, $this->_node[$nodeKey]);
                if (!$config) throw new Exception(‘Cache config Error‘);
                if (!isset($this->_memcache[$config])) {
                        $this->_memcache[$config] = new Memcache;
                        list($host, $port) = explode(‘:‘, $config);
                        $this->_memcache[$config]->connect($host, $port);
                }
                return $this->_memcache[$config];
        }
        
        /**
         * 采用二分法从虚拟memcache节点中查找最近的节点
         * @param unknown_type $m
         * @param unknown_type $b
         */
        private function _findServerNode($m = 0, $b = 0) {
            $total = count($this->_nodeData);
            if ($total != 0 && $b == 0) $b = $total - 1;
            if ($m < $b){
                $avg = intval(($m+$b) / 2);
                if ($this->_nodeData[$avg] == $this->_keyNode) return $this->_nodeData[$avg];
                elseif ($this->_keyNode < $this->_nodeData[$avg] && ($avg-1 >= 0)) return $this->_findServerNode($m, $avg-1);
                else return $this->_findServerNode($avg+1, $b);
            }
                if (abs($this->_nodeData[$b] - $this->_keyNode) < abs($this->_nodeData[$m] - $this->_keyNode))  return $this->_nodeData[$b];
                else return $this->_nodeData[$m];
        }
        
        public function set($key, $value, $expire = 0) {
                return $this->_connectMemcache($key)->set($key, json_encode($value), 0, $expire);
        }
        
        public function add($key, $value, $expire = 0) {
                return $this->_connectMemcache($key)->add($key, json_encode($value), 0, $expire);
        }
        
        public function get($key) {
                return json_decode($this->_connectMemcache($key)->get($key), true);
        }
        
        public function delete($key) {
                return $this->_connectMemcache($key)->delete($key);
        }
        
}
$runData[‘BEGIN_TIME‘] = microtime(true);
//测试一万次set加get
for($i=0;$i<10000;$i++) {
        $key = md5(mt_rand());
        $b = memcacheHashMap::getInstance()->set($key, time(), 10);
}

var_dump(number_format(microtime(true) - $runData[‘BEGIN_TIME‘],6));
$runData[‘BEGIN_TIME‘] = microtime(true); $m= new Memcache;
$m->connect(‘127.0.0.1‘, 11211); 
for($i=0;$i<10000;$i++) {
        $key = md5(mt_rand());
        $b = $m->set($key, time(), 0, 10);
}
var_dump(number_format(microtime(true) - $runData[‘BEGIN_TIME‘],6));

//测试结果,采用一致性哈希分布效率比原生单台速度相差5倍左右

时间: 2024-08-23 11:38:48

【转载】memcache分布式 [一致性hash算法] 的php实现的相关文章

memcache分布式 [一致性hash算法] 的php实现

最近在看一些分布式方面的文章,所以就用php实现一致性hash来练练手,以前一般用的是最原始的hash取模做分布式,当生产过程中添加或删除一台memcache都会造成数据的全部失效,一致性hash就是为了解决这个问题,把失效数据降到最低,相关资料可以google一下! php实现效率有一定的缺失,如果要高效率,还是写扩展比较好经测试,5个memcache,每个memcache生成100个虚拟节点,set加get1000次,与单个memcache直接set加get慢5倍,所以效率一般,有待优化!实

memcache的一致性hash算法使用

一.概述 1.我们的memcache客户端(这里我看的spymemcache的源码),使用了一致性hash算法ketama进行数据存储节点的选择.与常规的hash算法思路不同,只是对我们要存储数据的key进行hash计算,分配到不同节点存储.一致性hash算法是对我们要存储数据的服务器进行hash计算,进而确认每个key的存储位置.  2.常规hash算法的应用以及其弊端 最常规的方式莫过于hash取模的方式.比如集群中可用机器适量为N,那么key值为K的的数据请求很简单的应该路由到hash(K

【转载】对一致性Hash算法,Java代码实现的深入研究

原文地址:http://www.cnblogs.com/xrq730/p/5186728.html 一致性Hash算法 关于一致性Hash算法,在我之前的博文中已经有多次提到了,MemCache超详细解读一文中"一致性Hash算法"部分,对于为什么要使用一致性Hash算法.一致性Hash算法的算法原理做了详细的解读. 算法的具体原理这里再次贴上: 先构造一个长度为232的整数环(这个环被称为一致性Hash环),根据节点名称的Hash值(其分布为[0, 232-1])将服务器节点放置在这

memcached 分布式 一致性hash算法demo

一致性Hash分布算法分4个步骤:步骤1:将一个32位整数[0 ~ (2^32-1)]想象成一个环,0 作为开头,(2^32-1) 作为结尾,当然这只是想象.步骤2:通过Hash函数把KEY处理成整数.这样就可以在环上找到一个位置与之对应.步骤3:把Memcached服务器群映射到环上,使用Hash函数处理服务器对应的IP地址即可.步骤4:把数据映射到Memcached服务器上.查找一个KEY对应的Memcached服务器位置的方法如下:从当前KEY的位置,沿着圆环顺时针方向出发,查找位置离得最

分布式缓存的一致性hash算法

基本场景 比如你有 N 个 cache 服务器(后面简称 cache ),那么如何将一个对象 object 映射到 N 个 cache 上呢,你很可能会采用类似下面的通用方法计算 object 的 hash 值,然后均匀的映射到到 N 个 cache : 常规取余的hash算法 hash(key) % N 对于N台缓存服务器构成的集群缓存,依次编号为0 - (N-1)先对要存储的key进行hash取值,然后用hash值对N取余,得到一个在缓存服务器编号区间的一个数字,则将当前key存到这台服务器

分布式缓存技术memcached学习系列(四)—— 一致性hash算法原理

文章主目录 分布式一致性hash算法简介 分布式一致性hash算法使用背景 环形hash空间 映射key到环形hash空间 映射server节点到hash空间 映射key到server节点 添加server节点 删除server节点 虚拟节点的引入 节点变化数据分流的问题 一致性hash算法与取模算法的比较 参考文档 回到顶部 分布式一致性hash算法简介 当你看到“分布式一致性hash算法”这个词时,第一时间可能会问,什么是分布式,什么是一致性,hash又是什么.在分析分布式一致性hash算法

分布式memcached学习(四)&mdash;&mdash; 一致性hash算法原理

    分布式一致性hash算法简介 当你看到"分布式一致性hash算法"这个词时,第一时间可能会问,什么是分布式,什么是一致性,hash又是什么.在分析分布式一致性hash算法原理之前,我们先来了解一下这几个概念. 分布式 分布式(distributed)是指在多台不同的服务器中部署不同的服务模块,通过远程调用协同工作,对外提供服务. 以一个航班订票系统为例,这个航班订票系统有航班预定.网上值机.旅客信息管理.订单管理.运价计算等服务模块.现在要以集中式(集群,cluster)和分布

Nginx+Memcache+一致性hash算法 实现页面分布式缓存(转)

网站响应速度优化包括集群架构中很多方面的瓶颈因素,这里所说的将页面静态化.实现分布式高速缓存就是其中的一个很好的解决方案... 1)先来看看Nginx负载均衡 Nginx负载均衡依赖自带的 ngx_http_upstream_module . ngx_http_memcached_module两大功能模块,其中一致性hash算法Nginx本身是不支持的,可以借助第三方模块: ngx_http_upstream_consistent_hash 或者直接使用淘宝的Tengine: http://te

[转载] 一致性hash算法释义

转载自http://www.cnblogs.com/haippy/archive/2011/12/10/2282943.html 一致性Hash算法背景 一致性哈希算法在1997年由麻省理工学院的Karger等人在解决分布式Cache中提出的,设计目标是为了解决因特网中的热点(Hot spot)问题,初衷和CARP十分类似.一致性哈希修正了CARP使用的简单哈希算法带来的问题,使得DHT可以在P2P环境中真正得到应用. 但现在一致性hash算法在分布式系统中也得到了广泛应用,研究过memcach