class memcacheHash {

    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;
}
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 = memcacheHash::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));

总结:多台存储会慢一些。具体时间,请自行运行。

Memcache 分布式存储 【一致性Hash】crc32的更多相关文章

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

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

  2. memcache的一致性hash算法

    <?php /** * 一致性哈希memcache分布式,采用的是虚拟节点的方式解决分布均匀性问题,查找节点采用二分法快速查找 * the last known user to change t ...

  3. memcache的一致性hash算法使用

    一.概述 1.我们的memcache客户端(这里我看的spymemcache的源码),使用了一致性hash算法ketama进行数据存储节点的选择.与常规的hash算法思路不同,只是对我们要存储数据的k ...

  4. 关于memcache分布式一致性hash

    consistent hashing 算法早在 1997 年就在论文 Consistent hashing and random trees 中被提出,目前在 cache 系统中应用越来越广泛: 1  ...

  5. tornado--SESSION框架,一致性hash,分布式存储

    预备知识 tornado框架session要自己写 cookie存储在客户端浏览器上,session数据放在服务器上 session依赖cookie 扩展tornado,返回请求前自定义session ...

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

    网站响应速度优化包括集群架构中很多方面的瓶颈因素,这里所说的将页面静态化.实现分布式高速缓存就是其中的一个很好的解决方案... 1)先来看看Nginx负载均衡 Nginx负载均衡依赖自带的 ngx_h ...

  7. 【转】分布式存储和一致性hash

    本文我将对一致性算法作介绍,同时谈谈自己对一致性hash和一般意义上的hash算法的区别 hash是什么 hash即hash算法,又称为散列算法,百度百科的定义是 哈希算法将任意长度的二进制值映射为较 ...

  8. php一致性hash性能测试(flexihash/memcache/memcached)

    一致性hash的使用在PHP中有三种选择分别是原生的memcache扩展,memcached扩展,还有一个是网上比较流行的flexihash类. 最近有项目需要使用flexihash类操作memcac ...

  9. php 实现一致性hash 算法 memcache

    散列表的应用 涉及到数据查找比对,首先考虑到使用HashSet.HashSet最大的好处就是实现查找时间复杂度为O(1).使用HashSet需要解决一个重要问题:冲突问题.对比研究了网上一些字符串哈希 ...

随机推荐

  1. 51nod 1122 机器人走方格 V4 【矩阵快速幂】

    首先建立矩阵,给每个格子编号,然后在4*4的格子中把能一步走到的格子置为1,然后乘n次即可,这里要用到矩阵快速幂 #include<iostream> #include<cstdio ...

  2. 小程序各种授权封装、saveImageToPhotosAlbum、chooseAddress、getUserInfo、getLocation,保存图片、获取用户信息、获取位置信息、收货地址等

    代码略多,请异步 github __点击链接

  3. 我的周记5——"侵略如火,不动如山"

    这周发生的事儿 最近同事晋升的参加答辩,还有的同事要转岗走了.难受... 有时候自己常常想,我是不是应该也要走了. 这儿的人好优秀呀,又舍不得离开.但是这里太安逸了,接触不到技术,靠自学呢 又感觉力不 ...

  4. 标准行cp功能

    #include<stdio.h> int main(int argc,char *argv[]) { FILE *src_fp,*des_fp; ]={}; ) { printf(&qu ...

  5. JAVA 毕业设计 辅导

    JAVA 毕业设计 辅导   =======================================================  

  6. 题解报告:hdu 1230 火星A+B(字符串)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1230 Problem Description 读入两个不超过25位的火星正整数A和B,计算A+B.需要 ...

  7. bootstrap datatable项目封装

    (function($) {     $.fn.formJSON = function() {         var serializeObj = {};         var array = t ...

  8. Spring注解驱动开发之扩展原理

    前言:现今SpringBoot.SpringCloud技术非常火热,作为Spring之上的框架,他们大量使用到了Spring的一些底层注解.原理,比如@Conditional.@Import.@Ena ...

  9. 【原】无脑操作:Eclipse + Maven + jFinal + MariaDB 环境搭建

    一.开发环境 1.windows 7 企业版 2.Eclipse IDE for Enterprise Java Developers  Version: 2019-03 (4.11.0) 3.JDK ...

  10. (6)《Head First HTML与CSS》学习笔记---结尾、《HTML5权威指南》读书笔记

    1.内联元素的外边距.内边距与块元素稍有不同. 如果一个内联元素四周都增加外边距,只能看到左边和右边会增加空间:你也可以对内联元素的上下增加内边距,不过这个内边距不会影响包围它的其他内联元素的间距—— ...