记录memcache分布式策略及算法
摘要
http://wenku.baidu.com/link?url=eUmpWDGFiFguyQLxwmXwRYmbnW7Wm1Bo79dGoomSnmOPWDIA5-FFSTNRI7MBQq8QGsSGjyR1aFzIqeCe8xXNRZZOfm8LZ5xrck2quS6LZt_
http://blog.csdn.net/mayongzhan/article/details/4298834
http://bbs.phpchina.com/forum.php?mod=viewthread&tid=233897
经测试,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 <nash.xiong@gmail.com>
- * @copyright Copyright © 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倍左右
记录memcache分布式策略及算法的更多相关文章
- memcache分布式 [一致性hash算法] 的php实现
最近在看一些分布式方面的文章,所以就用php实现一致性hash来练练手,以前一般用的是最原始的hash取模做分布式,当生产过程中添加或删除一台memcache都会造成数据的全部失效,一致性hash就是 ...
- MemCache分布式缓存的一个bug
Memcached分布式缓存策略不是由服务器端至支持的,多台服务器之间并不知道彼此的存在.分布式的实现是由客户端代码(Memcached.ClientLibrary)通过缓存key-server映射来 ...
- memcache分布式部署的原理分析
下面本文章来给各位同学介绍memcache分布式部署的原理分析,希望此文章对你理解memcache分布式部署会有所帮助哦. 今天在封装memcache操作类库过程中,意识到一直以来对memcach ...
- 美团技术分享:深度解密美团的分布式ID生成算法
本文来自美团技术团队“照东”的分享,原题<Leaf——美团点评分布式ID生成系统>,收录时有勘误.修订并重新排版,感谢原作者的分享. 1.引言 鉴于IM系统中聊天消息ID生成算法和生成策略 ...
- memcache分布式小实例
<?php /** * 分布式的 memcache set 实现 */ /** * 创建缓存实现memcache 添加分布式服务器 并设置权限 */ function createCache() ...
- 分布式一致性hash算法
写在前面 在学习Redis的集群内容时,看到这么一句话:Redis并没有使用一致性hash算法,而是引入哈希槽的概念.而分布式缓存Memcached则是使用分布式一致性hash算法来实现分布式存储. ...
- memcache 分布式缓存
转载地址:http://www.cnblogs.com/phpstudy2015-6/p/6713164.html 作者:那一叶随风 1.memcached分布式简介 memcached虽然称为“分布 ...
- 理解分布式id生成算法SnowFlake
理解分布式id生成算法SnowFlake https://segmentfault.com/a/1190000011282426#articleHeader2 分布式id生成算法的有很多种,Twitt ...
- 分布式 ID 生成算法 — SnowFlake
一.概述 分布式 ID 生成算法的有很多种,Twitter 的 SnowFlake 就是其中经典的一种. SnowFlake 算法生成 ID 的结果是一个 64bit 大小的整数,它的结构如下图: 1 ...
随机推荐
- CSU 1424 Qz’s Maximum All One Square
原题链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1424 逐渐找到做这种题的感觉了. 二分法.g[i][j]存储坐标(i, j)的值,s[i ...
- django的orm获取字段去重值
如果要用django的ORM获取一个表字段所有可能的去重值. 网上找了很多,都是用distinct关键字,但如何没有随后的order_by, 还是达不到要求的. 最后搞定. 参考URL http:// ...
- TPC-H数据导入MySQL教程
0. TPC-H是啥 TPC-H是TPC提供的一个benchmark,用来模拟一个现实中的商业应用,可以生成一堆虚构的数据,且自带一些查询,可以导入到各种数据库中来模拟现实需求,检查性能. 具体是怎样 ...
- fastdfs5.11+centos7.2 按照部署(三)【转载】
1.测试 前面两篇博文已对FastDFS的安装和配置,做了比较详细的讲解.FastDFS的基础模块都搭好了,现在开始测试下载. 1.1 配置客户端 同样的,需要修改客户端的配置文件: vim /etc ...
- linux 驱动程序 HelloWorld
Linux驱动可以直接编译进内核,也可以以模块的形式进行加载,前者比较复杂,本文就以模块的形式加载! vi helloi_driver.c #include <linux/init.h> ...
- java.lang.ClassCastException: android.widget.ImageButton异常处理
在调程序时总是出现异常关闭的现象,log显示: 03-26 07:58:09.528: E/AndroidRuntime(398): Caused by: java.lang.ClassCastExc ...
- mysql 事务回滚
begindeclare t_error integer default 0; //添加变量t_error并赋初始值为0declare continue handler for sqlexcepti ...
- 将内存图像数据封装成QImage V2
转:http://www.cnblogs.com/bibei1234/p/3161555.html 如何将内存图像数据封装成QImage 当采用Qt开发相机数据采集软件时,势必会遇到采集内存图像并进行 ...
- HDU 6183 Color it
线段树. 假设只有一种颜色,因为每次询问有一个$x$一定是$1$,那么我可以想办法找出每一个$y$最小的$x$是多少,如果最小的都不符合,那么一定不符合,因为更新变成了单点更新,询问是区间询问最小值, ...
- java 数组冒泡排序、转置(降序)
1.java 数组冒泡排序 排序的基本原理(升序): 原始数据: 2 .1 .9 .0 .5 .3 .7 .6 .8: 第一次排序: 1 .2 .0 .5 .3 .7 .6 .8 .9 : 第二次 ...