<?php
/**
* 一致性哈希memcache分布式,采用的是虚拟节点的方式解决分布均匀性问题,查找节点采用二分法快速查找
* the last known user to change this file in the repository <$LastChangedBy: nash.xiong $>
* @author nash.xiong <nash.xiong@gmail.com>
* @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;
}
/**
* 采用二分法从虚拟memcache节点中查找最近的节点
* @param unknown_type $m
* @param unknown_type $b
*/
private function _findServerNode($m = 0,$b = 0) {
$totle = count($this->_nodeData);
if($totle != 0 && $b == 0) $b = $totle - 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);
}
}
    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);
}
}

最新文章

  1. C# 文件下载 : WinINet
  2. 关于EventSource的精华
  3. Hadoop学习笔记—20.网站日志分析项目案例(一)项目介绍
  4. django views中提示cannot convert dictionary update sequence element #0 to a sequence错误
  5. linux curl 命令详解,以及实例
  6. Windows 8.1 Enterprise 下 安装 Eclipse 官方中文包后无法输入任何内容
  7. A手机等的网络udp广播,收到广播以后回复udp消息
  8. IntelliJ IDEA 比较当前版本文件与历史文件
  9. 【转】IOS的处理touch事件处理(依照手指的移动移动一个圆,开发环境用的ios7,storyboard)-- 不错
  10. Java的JDBC事务详解(转)
  11. LeapMotion预览——什么是LeapMotion
  12. C#使用多态求方形面积周长和圆的面积周长
  13. [置顶] 图书推荐:SQL Server 2012 T-SQL基础 Itzik Ben-Gan
  14. SPSS Modeler数据挖掘项目实战(数据挖掘、建模技术)
  15. Appium 出现 &gt; error: com.test/.activity1 never started. Current: com.test/.activity2
  16. C#序列化总结
  17. Java8之Lambda表达式基础
  18. js设置元素不能编辑
  19. 对象属性的描述:writable、enumerable、configurable
  20. 多个gridSelect引用同一个dizData

热门文章

  1. oracle procedure存储过程(pl/sql)_使用declare cursor_begin end嵌套
  2. C++_直接插入排序(纯C版)
  3. windows mysql utf-8中文乱码解决方法
  4. JS获取事件源对象
  5. myeclipse web 包名保留字与servlet冲突
  6. 使用dispatch_group实现并封装分组并发网络请求
  7. ArcGIS Server 10.2 实战(四)格栅动态配色服务
  8. hdu 3440 差分约束
  9. 如何通过PhpMyAdmin批量删除MYSQL数据库数据表
  10. Android开发中的PhoneGap基本使用