Memcached常规应用与分布式部署方案
1、Memcached常规应用
$mc = new Memcache();
$mc->conncet('127.0.0.1', 11211);
$sql = sprintf("SELECT * FROM users WHERE uid = %d", $_GET['uid']);
$key = md5($sql);
//检测结果是否已经被缓存
if( ! $data = $mc->get($key)){
//没有缓存则直接从数据库读取
mysql_conncet('localhost', 'test', 'test');
mysql_select_db('test');
while($row = mysql_fetch_object(mysql_query($sql))){
$data[] = $row;
}
//并将查询结果缓存
$mc->add($key, $data);
}
var_dump($data);
说明:首先通过md5()将SQL语句转化成一个唯一的KEY,并用此KEY查询Memcached检测是否已经缓存,是的话在直接返回结果,否则先查询数据库再缓存,并返回结果。这样,下次使用此KEY就可以直接返回结果了。
2、Memcached分布式部署方案,对于多台Memcached服务器,怎么确定一个数据应该保存到哪台服务器呢?有两种方案,一是普通Hash分布,二是一致性Hash分布。下面详细说明。
方案一:简单的取模运算
<?php //Hash函数
function mHash($key){
$md5 = substr(md5($key), 0, 8);
$seed = 31;
$hash = 0;
for($i = 0; $i < 8; $i++){
$hash = $hash * $seed + ord($md5{$i});
$i++;
}
return $hash & 0x7FFFFFFF;
}
//假设有2台Memcached服务器
$servers = array(
array('host' => '192.168.1.1', 'port' => 11211),
array('host' => '192.168.1.1', 'port' => 11211)
);
$key = 'MyBlog';
$value = 'http://www.cnblogs.com/gide';
$sc = $servers[mHash($key) % 2];
$memcached = new Memcached($sc);
$memcached->set($key, $value);
说明:首先通过MD5函数把KEY处理成32位字符串,然后截取前8位,再经过Hash算法处理成一个整数并返回。利用这个整数与Memcached服务器数量取模,决定当前KEY存储于哪台Memcached服务器,就完成了Memcached的分布式部署。可想而知,当要读取KEY的值时,依然是先要通过Hash算法判断存储于哪台服务器
方案二:一致性hash部署
<?php class FlexiHash{
//服务器列表
private $serverList = array();
//记录是否已经排序
private $isSorted = FALSE;
//添加一台服务器
public function addServer($server){
$hash = $this->mHash($server);
if(!isset($this->serverList[$hash])){
$this->serverList[$hash] = $server;
}
//需要重新排序
$this->isSorted = FALSE;
return TRUE;
}
//移除一台服务器
public function removeServer($server){
$hash = $this->mHash($server);
if(isset($this->serverList[$hash])){
unset($this->serverList[$hash]);
}
//需要重新排序
$this->isSorted = FALSE;
return TRUE;
}
//在当前服务器列表查找合适的服务器
public function lookup($key){
$hash = $this->mHash($key);
//先进行倒序排序操作
if(!$this->isSorted){
krsort($this->serverList, SORT_NUMERIC);
$this->isSorted = TRUE;
}
//圆环上顺时针方向查找当前KEY紧邻的一台服务器
foreach($this->serverList as $pos => $server){
if($hash >= $pos) return $server;
}
//没有找到则返回顺时针方向最后一台服务器
return $this->serverList[count($this->serverList) - 1];
}
//Hash函数
private function mHash($key){
$md5 = substr(md5($key), 0, 8);
$seed = 31;
$hash = 0;
for($i = 0; $i < 8; $i++){
$hash = $hash * $seed + ord($md5{$i});
$i++;
}
return $hash & 0x7FFFFFFF;
}
}
?>
说明:一致性Hash分布算法分4个步骤:
步骤1:将一个32位整数[0 ~ (2^32-1)]想象成一个环,0 作为开头,(2^32-1) 作为结尾,当然这只是想象。
步骤2:通过Hash函数把KEY处理成整数。这样就可以在环上找到一个位置与之对应。
步骤3:把Memcached服务器群映射到环上,使用Hash函数处理服务器对应的IP地址即可。
步骤4:把数据映射到Memcached服务器上。查找一个KEY对应的Memcached服务器位置的方法如下:从当前KEY的位置,沿着圆环顺时针方向出发,查找位置离得最近的一台Memcached服务器,并将KEY对应的数据保存在此服务器上。
具体应用:
<?php
$hserver = new FlexiHash();
//初始5台服务器
$hserver->addServer("192.168.1.1");
$hserver->addServer("192.168.1.2");
$hserver->addServer("192.168.1.3");
$hserver->addServer("192.168.1.4");
$hserver->addServer("192.168.1.5");
echo "save key1 in server: ", $hserver->lookup('key1'), "<br/>";
echo "save key2 in server: ", $hserver->lookup('key2'), "<br/>";
echo '===============================================<br/>';
//移除1台服务器
$hserver->removeServer("192.168.1.4");
echo "save key1 in server: ", $hserver->lookup('key1'), "<br/>";
echo "save key2 in server: ", $hserver->lookup('key2'), "<br/>";
echo '===============================================<br/>';
//添加1台服务器
$hserver->addServer('192.168.1.6');
echo "save key1 in server: ", $hserver->lookup('key1'), "<br/>";
echo "save key2 in server: ", $hserver->lookup('key2');
?>
//测试结果如下:
save key1 in server: 192.168.1.4
save key2 in server: 192.168.1.2
==================================
save key1 in server: 192.168.1.3
save key2 in server: 192.168.1.2
==================================
save key1 in server: 192.168.1.3
save key2 in server: 192.168.1.2
不过Memcached自带了addServer
Memcached::addServer — 向服务器池中增加一个服务器
public bool Memcached::addServer ( string $host , int $port [, int $weight = 0 ] )
host
memcached服务端主机名。如果主机名无效,相关的数据操作的返回代码将被设置为Memcached::RES_HOST_LOOKUP_FAILURE。
port
memcached服务端端口号,通常是11211。
weight
此服务器相对于服务器池中所有服务器的权重。此参数用来控制服务器在操作时被选种的概率。这个仅用于一致性 分布选项,并且这个值通常是由服务端分配的内存来设置的。
成功时返回 TRUE, 或者在失败时返回 FALSE。
<?php
$m = new Memcached(); $m->addServer('mem1.domain.com', 11211, 33);
$m->addServer('mem2.domain.com', 11211, 67);
完毕!
Memcached常规应用与分布式部署方案的更多相关文章
- Window Redis分布式部署方案 java
Redis分布式部署方案 Window 1. 基本介绍 首先redis官方是没有提供window下的版本, 是window配合发布的.因现阶段项目需求,所以研究部署的是window版本的,其实都 ...
- Memcache分布式部署方案
基础环境 其实基于PHP扩展的Memcache客户端实际上早已经实现,而且非常稳定.先解释一些名词,Memcache是danga.com的一个开源项目,可以类比于MySQL这样的服务,而PHP扩展的M ...
- zookeeper分布式部署方案
版本:http://apache.fayea.com/zookeeper/zookeeper-3.4.8/环境:debian 7/8说明:最低配置3台步骤:1.下载zookeeper-3.4.8并解压 ...
- memcached缓存分布式部署方案
一.分布式方案介绍 比较流行的两种方案: 1.取余分布: 计算key的哈希值,与服务器数量取余,得到目标服务器.优点:实现简单,当某台服务器不可用时,故障转移方便:缺点:当增减服务器时, Key与服务 ...
- Linux-Memcache分布式部署方案(magent代理解决单点故障)
Memcached的特点 Memcached作为高速运行的分布式缓存服务器具有以下特点. 1. 协议简单:memcached的服务器客户端通信并不使用复杂的MXL等格式, 而是使用简单的基于文本的协议 ...
- 一文读懂 Redis 分布式部署方案
为什么要分布式 Redis是一款开源的基于内存的K-V型数据库,因为内存访问速度快,一般被用来做系统的缓存. Redis作为单机部署能够支持业务简单,数据量不大的系统需求,但在实际应用中,一旦系统规模 ...
- 矢量切片应用中geoserver与geowebcache分布式部署方案
在进行GIS项目开发中,常使用Geoserver作为开源的地图服务器,Geoserver是一个JavaEE项目,常通过Tomcat进行部署.而GeoWebCache是一个采用Java实现用于缓存WMS ...
- Redis集群的分布式部署
3.2.2:Redis Cluster: Redis 分布式部署方案: 1) 客户端分区:由客户端程序决定 key 写分配和写入的 redis node,但是需要客户端自己处理写入 分配.高可用管 ...
- 项目分布式部署那些事(2):基于OCS(Memcached)的Session共享方案
在不久之前发布了一篇"项目分布式部署那些事(1):ONS消息队列.基于Redis的Session共享,开源共享",因为一些问题我们使用了阿里云的OCS,下面就来简单的介绍和分享下相 ...
随机推荐
- win7下安装mysql
(1)官网下载mysql: http://dev.mysql.com/downloads/mysql/ (2)解压后,进入到该目录下,将my-default.ini文件复制一份改名为my.ini 打开 ...
- HtDP读后感
我小时候很喜欢电脑. 不是听音乐,也不是玩游戏.纯粹是好奇:为什么一部冷冰冰的机器插上电源之后居然能如此强大.我每个月都期盼着订阅的电脑杂志快点到,到手以后总先上手试试里面的"奇淫巧技&qu ...
- aix 6+ mount 光驱
AIX 挂载光驱的方法 系统环境: [root@Big A:/1]#oslevel -s6100-06-00-0000 [root@Big A:/]#crfs -v cdrfs -p ro -d '/ ...
- Int16, Int32, Int64 范围
Int16, 等于short, 占2个字节. -32768 32767 Int32, 等于int, 占4个字节. -2147483648 2147483647 Int64, 等于long, 占8个字节 ...
- DOM、JDOM、DOM4J的区别(转载)
DOM.JDOM.DOM4J的区别 分类: XML2012-06-11 20:47 5576人阅读 评论(6) 收藏 举报 文档xmlcollectionsjavaapi工作 dom是解析xml的底层 ...
- u盘安装ubuntu
安装ubuntu 准备工作:首先需要安装好UltraISO(版本要比较新,有些老版本有照做后不能安装的错误) 准备好一个U盘. 下载好ubuntu光盘.(我用的12.04版) 步骤: 1.制作安装U盘 ...
- java 字符串截取
截取指定长度的字符串,如果超出就用more的内容来替换 截取的字节数,截取的时候,有可能会少截取一位(当最后一位是1个双字节的话,会少截取一个) public class Test { publ ...
- 利用Java自带的MD5加密
package test.md5; import java.security.MessageDigest; public class MD5Util { public final static Str ...
- java操作word,excel,pdf
在平常应用程序中,对office和pdf文档进行读取数据是比较常见的功能,尤其在很多web应用程序中.所以今天我们就简单来看一下java对word.excel.pdf文件的读取.本篇博客只是讲解简单应 ...
- JAVA程序提示错误:需要class,interface或enum解决方法
错误详情: 解决办法:主要是用非记事本编写代码文件,存在编码格式转换问题.重新先建一个记事本程序,然后把源代码粘贴到该文件下,用javac 类名.java编译,java 文件名运行该程序即可