了解Memcache
Memcache是一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的hash表,它能够用来存储各种格式的数据,包括图形、视频、文件以及数据库检索的结果等。简单的说就是将数据调用到内存中,然后从内存中读取,从而大大提高读取速度。Memcached是以守护程序方式运行于一个或多个服务器中,随时会接收客户端的连接和操作。其基本的原理就是将数据缓冲到内存中,因为程序读取内存的速度远远大于进行磁盘IO读取的速度。缺点就是不能持久化存储,断电后缓冲的数据会被丢失。
很多人会把memcache和memcached混淆了,memcache一般指的是php的mmecache扩展,在PECL(PHP Extension Community Library http://pecl.php.net/)中 。memcached则是服务器端的一个应用程序,该应用程序常驻内存,能提供客户端连接然后读取和保存数据。换言之,就是用php的memcache扩展可以连接到memcached内存缓存服务器。当然memcache也有其他语言的API接口。
安装php memcache扩展
本示例是介绍Linux下php memcache扩展的安装,Windows下的安装就比较简单了(LAMP/XAMPP下都可以鼠标操作)。首先我们去PHP官网下载memcache最新稳定版的扩展
1. 打开 http://pecl.php.net/packages.php 点击cacheing找到memcache扩展,这里也有memcache和memcached我们安装memcache(memcache是PECL扩展,memcached是libmemcached扩展,两个功能基本差不多 区别:http://www.dewen.org/q/844)
注:windows下memcache.dll的文件可以到php.net下搜索到,linux下需要自己编译安装
$ cd /var/ftp/upload/memcache/
$ wget http://pecl.php.net/get/memcache-2.2.7.tgz
$ tar -zxvf memcache-2.2.7.tgz
$ cd memcache-2.2.7
# 如果未安装phpize可使用 yum install php-devel安装
$ phpize
$ ./configure
$ make && make install
# 安装成功后需要把安装好的.so文件拷贝到php的extionsion扩展目录,然后在php.ini中加入 extionsion=memcache.so
$ cp mocules/memcache.so /usr/lib/php/modules/
# 如果你找不到你的扩展目录,可使用whereis php 查看
$ vi /ect/php.ini 加入
extension = /usr/lib/php/modules
extension = memcache.so
#重启apache服务器
$ /etc/init.d/httpd restart
新建一个文件,查看是否安装成功~
<?php phpinfo() ?>
总结以上,我们就已经成功安装了php的memcache扩展程序了~下面就可以使用php memcahce api连接到memcached服务器喽~(好像我们还没装memcached服务器哦)
安装memcached服务器
安装memcached服务器,该软件包可以从官方下载到 http://memcached.org/ 下载后解压编译安装即可,注意的是memcached依赖于libevent。
$ wget http://memcached.googlecode.com/files/memcached-1.4.15.tar.gz
$ tar -zxvf memcached-1.4.15.tar.gz
#查询是否安装libevent,未安装则安装之
$ ls -al /usr/lib | grep libevent
$ curl -O http://www.monkey.org/~provos/libevent-2.0.13-stable.tar.gz
$ tar -zxvf libevent-2.0.13-stable.tar.gz
$ cd libevent-2.0.13-stable-tar.gz
$ ./configure --prefix=/usr/local/libevent
$ make ; make install
# 安装memcached
$ cd memcached-1.4.15
$ ./configure --with-libevent=/usr/local/libevent --prefix=/usr/local/memcached
$ make && make install
#启动Memcached
$ /usr/local/memcached/bin/memcached -d start -m 32 -u root -p 11211
#检查是否成功安装
$ ls -al /usr/local/bin/mem*
$ ps -aux
配置Memcached服务
配置Memcached参数
memcached启动参数
-p 指定端口号(默认11211)-U <num> UDP监听端口 (默认: 11211, 0 时关闭)-s <file> 用于监听的UNIX套接字路径(禁用网络支持)-a <mask> UNIX套接字访问掩码,八进制数字(默认:0700)-m 指定最大使用内存大小(默认64MB)-t 线程数(默认4)-l <ip_addr> 绑定地址 (默认:所有都允许,无论内外网或者本机更换IP,有安全隐患,若设置为127.0.0.1就只能本机访问)-d start 启动memcached服务-d restart 重起memcached服务-d stop|shutdown 关闭正在运行的memcached服务-u <username> 绑定使用指定用于运行进程 <username> (只有root用户可以使用这个参数)-P <file> 将PID写入文件<file>,这样可以使得后边进行快速进程终止, 需要与 -d 一起使用-m 最大内存使用,单位MB。默认64MB www.2cto.com-M 内存耗尽时返回错误,而不是删除项-c 最大同时连接数,默认是1024-f 块大小增长因子,默认是1.25-n <bytes>最小分配空间,key+value+flags默认是48-k锁定所有内存页。注意你可以锁定的内存上限。试图分配更多内存会失败的,所以留意启动守护进程时所用的用户可分配的内存上限。(不是前面的 -u <username> 参数;在sh下,使用命令"ulimit -S -l NUM_KB"来设置。)-v 提示信息(在事件循环中打印错误/警告信息。)-vv 详细信息(还打印客户端命令/响应)-vvv 超详细信息(还打印内部状态的变化)-h 打印这个帮助信息并退出。-i 打印memcached和libevent的许可。-L 尝试使用大内存页(如果可用的话)。提高内存页尺寸可以减少"页表缓冲(TLB)"丢失次数,提高运行效率。 www.2cto.com为了从操作系统获得大内存页,memcached会把全部数据项分配到一个大区块。-D <char> 使用 <char> 作为前缀和ID的分隔符。这个用于按前缀获得状态报告。默认是":"(冒号)。如果指定了这个参数,则状态收集会自动开启;如果没指定,则需要用命令"stats detail on"来开启。-t <num> 使用的线程数(默认:4)-R 每个连接可处理的最大请求数。-C 禁用CAS。-b 设置后台日志队列的长度(默认:1024)-B 绑定协议 - 可能值:ascii,binary,auto(默认)-I 重写每个数据页尺寸。调整数据项最大尺寸。常用组合:/usr/local/memcached/bin/memcached -d -m 256 -p 11211 -u www -l 127.0.0.1
启动和停止Memcached
#启动Memcached
/usr/local/memcached/bin/memcached -d -m 4096 -p 11211 -u root -l 127.0.0.1 -c 10000 -P /tmp/memcached.pid
启动了一个Memcached守护进程:
监听来自本机的11211端口
最大占用内存4G
最大连接数1W(根据你服务器负载设置)
进程PID保持在/tmp/memcached.pid,可以用KILL关闭
#停止Memcached,先找出PID,然后kill
$ ps -ef |grep memcached
$ kill -9 1974
# 如果你要重新服务之需要再输入一次启动命令即可
设置Memcached开机自动启动
$ vi /etc/rc.d/rc.local
加入
/usr/local/memcached/bin/memcached -d -m 32 -l 127.0.0.1 -p 11211 -u root -l 127.0.0.1
重新启动系统后会自动启动Memcached服务
telnet链接Memcached
# 我再调试中发现链接不上Memcached,尝试kill所有memcached后重新启动了就可以了,注意使用-l参数(如果你设置-l 127.0.0.1则只能从本机连接memcached)
# 如果你未安装telnet则可以使用yum快速安装telnet客户端
$ yum install telnet-client
$ telnet 127.0.0.1 11211
输入stats可以查看一些运行参数
Memcached状态查看
使用PHP调用Memcached
第一部分我们安装了Memcache for php,安装后重启apache就可以使用php连接到memcached了,具体可以查看php的memcached api http://cn2.php.net/memcache
我写了一段测试代码测试将sphinx中的数据放入到memcached中,如下:
<form method=post>
<input name='s' type='input'/>
<input type='submit' />
</form>
<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST'){
#ae#:cho 'helol';exit;
error_reporting(E_ALL ^ E_NOTICE);
//
// $Id: test.php 2055 2009-11-06 23:09:58Z shodan $
//
// $Id
header("Content-type: text/html; charset=utf-8");
#echo 'a';exit;
$mem = new Memcache();
$mem->connect("127.0.0.1", 11211);
require ( "sphinxapi.php" );
$cl = new SphinxClient();
$cl->SetServer("127.0.0.1",9312);
$cl->SetArrayResult(true);
$keyword = $_POST['s'];
$result = $cl->Query($keyword,"src1");
//var_dump($cl);
//var_dump($result);
#echo G('START','END').'s';
//处理$result
$matches = isset($result['matches']) ? $result['matches'] : '';
if(is_array($matches)){
foreach ($matches as $v){
$ids[] = $v['id'];
}
}else{
print("<pre>");
print $cl->GetLastError();
print $cl->GetLastWarning();
//print "没找到了亲~";
print("</pre>");
return;
}
$ids = implode(',', $ids);
# 缓冲到memcache中
$ids_mem = $mem->get("ids_$ids");
if ($ids_mem){
var_dump("Memcached:<br/>");
var_dump( $ids_mem);
return;
}else{
G('START');
//拿着id ,拉库
$link = mysql_connect('10.2.4.14','root','123456') or die('mysql link fail!');
mysql_select_db('test',$link);
mysql_query("SET NAMES UTF8");
$sql = "select * from documents where id in({$ids})";
#G('START');
$result = mysql_query($sql,$link);
echo G('START','END');
//echo $sql;
$data = array();
while ($row = mysql_fetch_assoc($result))
{
$data[] = $row;
}
mysql_close($link);
// 关键字高亮
$p_titles = array();
$p_contents = array();
$build_opts= array(//查询结果集设置
'before_match'=> '<font color="red">',
'after_match'=> '</font>',
'limit'=> '130',
//'exact_phrase'=> true,
'single_passage'=> true,
'chunk_separator' => '',
);
foreach($data as $key=>$value)
{
$p_titles[$key] = $value['title'];
$p_contents[$key] = $value['content'];
}
$p_titles = $cl->BuildExcerpts($p_titles, 'src1', $keyword, $build_opts);
$p_contents = $cl->BuildExcerpts($p_contents, 'src1', $keyword, $build_opts);
foreach($data as $key=>$post)
{
$data[$key]['title'] = $p_titles[$key];
$data[$key]['content'] = $p_contents[$key];
}
$mem->set("ids_$ids", $data);
var_dump($data);
}
}
//setFilter 属性过滤,属性并不会被索引
#API http://www.coreseek.cn/docs/coreseek_3.2-sphinx_0.9.9.html#quick-tour
function G($start,$end='',$dec=4) {
static $_info = array();
if(is_float($end)) { // 记录时间
$_info[$start] = $end;
}elseif(!empty($end)){ // 统计时间
if(!isset($_info[$end])) $_info[$end] = microtime(TRUE);
return number_format(($_info[$end]-$_info[$start]),$dec);
}else{ // 记录时间
$_info[$start] = microtime(TRUE);
}
}
?>