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));

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

最新文章

  1. node-sass安装不成功的解决方案
  2. win7 hosts文件更改后无效,不生效问题
  3. MD5 加密的两种方法
  4. 李洪强漫谈iOS开发[C语言-023]-取余数运算符
  5. 高性能网络I/O框架-netmap源码分析
  6. 腾讯RTX登录提示失败问题及处理办法
  7. 深度克隆(对象、数组)--------百度IFE前端task2
  8. css3实现色子自动翻转效果
  9. 使用libvirt做适配的kvm虚拟机window server 2008 磁盘性能的提升
  10. SpringMVC 整合Jackson报错
  11. 示波器X1探头和X10探头
  12. ionic 兼容title居中显示和tab栏在显示底部
  13. 第二个spring,第一天
  14. Bootstrap-按钮相关的class
  15. react native项目的创建和运行
  16. IIS Media Service: Channel 小结
  17. iOS开发之--png图片编译时报错 (Command /Applications/Xcode.app/Contents/Developer/usr/bin/copypng failed with exit code 1 )
  18. Reconstruction(三维重建)文件被修改
  19. angular resolve路由
  20. SQL多表联查总结

热门文章

  1. 【Aizu - 0005 】GCD and LCM
  2. html 解决空格显示问题
  3. 有了Git这些操作,我再也不怕开发了!
  4. pycharm2017.1破解方法
  5. 牛客小白月赛5-D-阶乘(求n内每个数的阶乘相乘后尾数为0的个数)
  6. 2、IO流的分类和IO流体系
  7. Suricata是什么?
  8. .net简单的fileupload控件上传
  9. 使用nginx搭建简单文件服务器
  10. java获取公网ip以及物理地址和代理商