学习Memcached

好久没更新博客了,最近发布文章还是去年年底的事,不知不觉已过去了三个月。这期间,经历了不少事情,这些事情使我心烦意乱,都不能静下心来学习新技术,就更别说坐下来花两个小时去写一篇博客文章了。人生不如意十有八九,常想一二吧。好在最近,生活和工作慢慢回归平静,可以好好静下心来学习新东西和做一些思考了。由于新入职的公司使用了Memcached来缓解高流量高并发的问题,所以这两天把Memcached学习了一下,下面是我做的笔记:

一,简介

Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提供动态、数据库驱动网站的速度。Memcached基于一个存储键/值对的哈希表。其守护进程是用C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信。

目前,很多高流量高并发的网站正使用Memcached来完善自身应用服务,比如:Facebook,Twitter,YouTube,Wikipedia等等。可以说,Memcached在Web 2.0时代正变得越来越不可或缺。

二,安装(for Windows)

  1. 下载Memcached。首先需下载Memcached服务器端软件,地址:Click Here
  2. 将安装包解压到某一目录,如:D:\memcached。
  3. 进入到命令行(CMD)界面,输入“D:\memcached\memcached.exe -d install”命令安装,接着,输入“D:\memcached\memcached.exe -d start”命令启动memcache服务,这样Memcached服务器就搭建好了。
  4. 让Memcached对PHP可用。为了能在PHP中使用Memcached,必需安装memcache扩展。注意使用与自身PHP版本互相兼容的memcache扩展版本。将其放在PHP安装目录下的扩展目录ext下,然后,打开php.ini文件,在“Dynamic Extensions”部分,加入:extension=php_memcache.dll,接着重启Apache。
  5. 运行phpinfo命令,如果存在memcache,则表明memcached对PHP已可用。否则,请检查3,4步是否正确操作。

三,示例

1,“Hello World”程序

<?php
$memcache = new Memcache;
$memcache->connect("127.0.0.1", 11211);
$memcache->set('key', 'Hello World', 0, 60);
$val = $memcache->get('key');
echo $val;
?>

 如果安装成功,访问该脚本,在浏览器中就能打印“Hello World”字符串。

2,将从数据库中查询的10条结果进行缓存

在这个示例中,在用户第一次访问页面时,常规的去查询数据库,但会使用Memcached把从数据库中查询的10条数据进行缓存,当用户再次访问该页面时,就直接从内存中读取数据,而不是按一般思路那样再次去查询数据库,这样就减少了I/O开销,减轻了数据库的负担。下面是Memcache控制器代码:

<?php
/**
 * Personal Memcache Controller
 * 个人缓存控制器
 *
 **/
 class PMC
 {
	static private $instance = null;	// PMC对象实例
	private $memcache;
	
	public function __construct()
	{
		$this->memcache = new Memcache;
		global $memcache_servers;
		$server_number = count($memcache_servers);
		if ($server_number > 1)
		{
			for ($i=0; $i<$server_number; $i++)
			{
				$this->memcache->addServer($memcache_servers[$i]['host'], $memcache_servers[$i]['port']);
				$i++;
			}
		}
		else
		{
			if ( empty($memcache_servers[0]['host']) )
				exit('Please config the parameters of memcache server host!');
			
			$this->memcache->addServer($memcache_servers[0]['host'], !empty($memcache_servers[0]['port']) ? $memcache_servers[0]['port'] : 11211);
		}
	}
	
	static public function getInstance()
	{
		if (self::$instance == null)
			self::$instance = new PMC();
		return self::$instance;
	}
	
	public function get($key)
	{
		return $this->memcache->get($key);
	}
	
	public function set($key, $value, $flag=0, $expire=3600)
	{
		$this->memcache->set($key, $value, $flag, $expire);
	}
 }
 
?>

 该控制器了封装了对Memcache的实例化,添加Memcached Server,获取对象实例以及Memcache内置get和set操作,通过这个PMC类与Memcached服务器进行通信。

上面脚本中出现的$memcache_servers变量来自配置文件config.php,它实际上是一个由Memcached Server主机和端口为元素组成的二维数组。config.php文件定义了数据库和Memcached的相关信息,内容如下:

<?php
// 配置文件,包括数据库,Memcached等

// 数据库配置
define('DB_HOST',     '127.0.0.1');
define('DB_PORT',     '3306');
define('DB_USER',     'root');
define('DB_PASS',     '19880210');
define('DB_NAME',     'mem_demo');
define('DB_CHARSET',  'utf8');

// Memcached配置
define('MEMCACHE_LIFETIME', 60);
define('MEMCACHE_FLAG', 0);	// 0 => NO COMPRESSED; 1 => COMPRESSED
$memcache_servers = array(
	array(
		'host'   => '127.0.0.1',
		'port'   => 11211,
	),
	// Add more memcache server
);
?>

 接下来,我们在index.php文件中使用Memcached。该文件主要做两件事:一是,如果第一次访问,则从数据库mem_demo的数据表star_info中查询前10条记录,并使用Memcached将记录缓存到内存中。如果是再次访问,则直接从内存中取出数据。二是,记录下脚本运行时间,用以比较查询数据库操作和使用Memcached获取数据的快慢(粗略的比较)。

<?php
// for test
require 'define.php';
require WEB_ROOT.'\Conf\config.php';
require WEB_ROOT.'\Lib\PMC.php';
require WEB_ROOT.'\Lib\mysql.class.php';
require WEB_ROOT.'\Lib\Utils.class.php';

$begin_time = Utils::getTime();
$pmc = PMC::getInstance();
$test = new MysqlConnect(DB_HOST, DB_USER, DB_PASS, DB_NAME, DB_CHARSET);

function query_memcache($sql)
{
	$mem_key = md5($sql);
	global $pmc, $test;
	if (!$value = $pmc->get($mem_key))
	{
		$query = $test->query($sql);
		while ($item = $test->fetchArray($query))
			$result[] = $item;
		$value = $result;
		$pmc->set($mem_key, $result, MEMCACHE_FLAG, MEMCACHE_LIFETIME);
	}
	return $value;
}

$sql = 'SELECT * FROM `star_info` Limit 10';
//print_r(query_memcache($sql));exit;
$star = query_memcache($sql);
foreach ($star as $item){
	$display .= 'This is '.$item['name'].', from '.$item['country'].'. <img src='.$item['photo'].'><hr>';
}
echo $display;
$end_time = Utils::getTime();
$run = $end_time - $begin_time;
echo $run;

$test->close();

 可以看到,当再次访问index.php时,$run的值近似为零,说明Memcached确实起到了作用。最后,需要说明的是,以上只是一个DEMO,用以大致表明Memcached的工作原理,对于这点,我想目的已经达到。如果真正要部署到生产环境中,还需处理很多的细节。另外,在高流量高并发的环境下,部署多台Memcached服务器,确实能起到立竿见影的效果。

P.S. 这个DEMO的源代码托管在Github上,项目地址为:https://github.com/phplaber/memcached_demo。如果你有兴趣,你可以试着去完善和升级这个DEMO,而且我也鼓励你这么做。呵呵。

(完)

猜你喜欢

转载自phplaber.iteye.com/blog/1832789