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,下面就来简单的介绍和分享下相 ...
随机推荐
- python安装pycrypto报错error: command 'x86_64-linux-gnu-gcc' failed with exit status 1
系统3.19.0-15-generic #15-Ubuntu 安装pycrypto提示error: command 'x86_64-linux-gnu-gcc' failed with exit st ...
- 手机驱动无法正常安装,出现adb interface失败
手机一直无法用usb连接上电脑,试了各种方法,总是提示安装驱动失败,或者找不到文件. 在网上找了各种方法,后来结果证明,是我自己手贱了,... 方法: Win7系统用户已经碰到几次在安装adb驱动时提 ...
- java中final,finally和finalize的区别
final,finally和finalize的区别: final:最终的意思,可以修饰类,成员变量,成员方法 修饰类,类不能被继承 修饰变量,变量是常量 修饰方法,方法不能被重写 finally:是异 ...
- 《UML大战需求分析》阅读笔记2
在第三章往后的章节里面,作者着重描述了uml各个图的具体用法,首先则是类图. 类图则表示程序中所出现的用到的类,用方框来表示,方框中分为三行,第一行是类的名字,第二行是类的成员变量(属性),第三行是成 ...
- 2.Unable to instantiate Action, templateAction, defined for 'template_list' in namespace '/'templateAction
1.错误说没有命名空间'templateAction,但是在struts里写了这个,名字跟Action的名字是一样的,为什么会报这个错误 2.反复检查路径和名字,都没有问题 3.发现没有对其进行注入操 ...
- 关于eclipse在线下载安装android SDK没反应解决方法
虽然天朝将google这个服务器给和谐掉了 虽然我们也可以选择其他各类FQ软件 虽然你可能有其他手段解决 不过我还是要提供一个参考方法: 具体操作方式: 点击桌面左下角开始菜单中的搜索,把以下路径,复 ...
- 过滤器(servlet.filter)和拦截器(springmvc.interceptor)区别
①拦截器是基于java的反射机制的,而过滤器是基于函数回调. ②拦截器不依赖与servlet容器,过滤器依赖与servlet容器. ③拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求 ...
- 命令行查看linux发行版版本信息
有时候安装完自己的linux发行版系统(如ubuntu.centos.redhat.opensuse.--)时,把版本信息忽略了,又不想重启电脑,此时我们可以通过命令行方式来查看: 1.cat /et ...
- AndroidStudio Lod.d在LogCat中不输出
今天Log.d无论怎样都没有输出. 要在手机开发者选项那开启权限,莫名其妙,之前一直都没事的,具体操作参考:http://jingyan.baidu.com/article/84b4f56597e7b ...
- 对象池与.net—从一个内存池实现说起
本来想写篇关于System.Collections.Immutable中提供的ImmutableList里一些实现细节来着,结果一时想不起来源码在哪里--为什么会变成这样呢--第一次有了想写分析的源码 ...