memcache与memcached版本间的一个BUG:Memcache delete无效

the Memcache::delete(key) function is broken on several combinations of memcached+pecl-memcache combinations.

pecl-memcache 2.2.5 + memcached 1.4.2 - Memcache::delete(key) WORKS

pecl-memcache 2.2.5 + memcached 1.4.3 - Memcache::delete(key) DOES NOT WORK

pecl-memcache 2.2.5 + memcached 1.4.4 - Memcache::delete(key) WORKS

pecl-memcache 2.2.5 + memcached 1.4.5 - Memcache::delete(key) WORKS

pecl-memcache 3.0.4 + memcached 1.4.2 - Memcache::delete(key) WORKS

pecl-memcache 3.0.4 + memcached 1.4.3 - Memcache::delete(key) DOES NOT WORK

pecl-memcache 3.0.4 + memcached 1.4.4 - Memcache::delete(key) DOES NOT WORK

pecl-memcache 3.0.4 + memcached 1.4.5 - Memcache::delete(key) DOES NOT WORK

程序在线上部署时出现这样离奇的问题,真是愁死人。
在网上找到解决办法,不过,我最后将cached换成了redis~

http://5iwww.blog.51cto.com/856039/269348

使用 memcache 的过程中,遇到一个奇怪的问题,在 CentOS 环境下,PHP 的 memcache 扩展创建的客户端对象,在 delete 一个 key 的时候报错:
[25-Nov-2009 13:57:04] PHP Notice: Memcache::delete(): Server 192.168.10.131 (tcp 11211) failed with: CLIENT_ERROR bad command line format. Usage: delete [noreply]
可是在 Windows 环境下,用的人家编译好的 php_memcache-cvs-20090703-5.3-VC6-x86.dll (20KB) 却没问题!
在 Google 上找了半天,终于在 PHP 官方手册的评论中发现了线索:
http://php.net/manual/en/function.memcache-delete.php
请看 10-Nov-2009 11:17 这条,简短翻译一下:
memcache 这个 PECL 扩展的 2.2.5 稳定版本有一个错误,导致在向 memcached 1.4.3 调用 delete 方法时返回 false。
用 -vvv 模式运行 memcached 将显示出为什么 delete 调用失败:
CLIENT_ERROR bad command line format. Usage: delete
[noreply]
简单修改一下,在这个 PECL 扩展的 memcache.c 这个文件的 1494 行的 mmc_delete() 函数中。把 command_len 修改为下面这样:
command_len = spprintf(&command, 0, "delete %s", key);
去掉了弃用的第 3 个参数,然后 delete 就可以工作了。
再提示一下改动前的代码:
// command_len = spprintf(&command, 0, "delete %s %d", key, time);
修改完成后,重新编译出 memcache.so 即可。

修改源码并不能保证以后会出现什么问题。问题的根本是memcached 1.4.3版本同memcached 1.4.0版本的delete函数不一样。

我最后的解决方案是memcache用2.2.5,memcached用1.4.0版本。
经测试,一切OK..

CentOS(x86_64)下PHP安装memcache并配置扩展

[root@~]# pecl install memcache
downloading memcache-2.2.6.tgz ...
Starting to download memcache-2.2.6.tgz (35,957 bytes)
..........done: 35,957 bytes
11 source files, building
WARNING: php_bin /opt/php/bin/php appears to have a suffix /bin/php, but config variable php_suffix does not match
running: phpize
Configuring for:
PHP Api Version:         20090626
Zend Module Api No:      20090626
Zend Extension Api No:   220090626
Enable memcache session handler support? [yes] : n
running: make INSTALL_ROOT="/var/tmp/pear-build-root/install-memcache-2.2.6" install
Installing shared extensions:     /var/tmp/pear-build-root/install-memcache-2.2.6/opt/php/lib/php/extensions/no-debug-non-zts-20090626/
running: find "/var/tmp/pear-build-root/install-memcache-2.2.6" | xargs ls -dils
11370548   4 drwxr-xr-x 3 root root   4096 Jan  6 15:55 /var/tmp/pear-build-root/install-memcache-2.2.6
11370602   4 drwxr-xr-x 3 root root   4096 Jan  6 15:55 /var/tmp/pear-build-root/install-memcache-2.2.6/opt
11370603   4 drwxr-xr-x 3 root root   4096 Jan  6 15:55 /var/tmp/pear-build-root/install-memcache-2.2.6/opt/php
11370604   4 drwxr-xr-x 3 root root   4096 Jan  6 15:55 /var/tmp/pear-build-root/install-memcache-2.2.6/opt/php/lib
11370605   4 drwxr-xr-x 3 root root   4096 Jan  6 15:55 /var/tmp/pear-build-root/install-memcache-2.2.6/opt/php/lib/php
11370606   4 drwxr-xr-x 3 root root   4096 Jan  6 15:55 /var/tmp/pear-build-root/install-memcache-2.2.6/opt/php/lib/php/extensions
11370607   4 drwxr-xr-x 2 root root   4096 Jan  6 15:55 /var/tmp/pear-build-root/install-memcache-2.2.6/opt/php/lib/php/extensions/no-debug-non-zts-20090626
11370601 236 -rwxr-xr-x 1 root root 235639 Jan  6 15:55 /var/tmp/pear-build-root/install-memcache-2.2.6/opt/php/lib/php/extensions/no-debug-non-zts-20090626/memcache.so

Build process completed successfully
Installing '/opt/php/lib/php/extensions/no-debug-non-zts-20090626/memcache.so'
install ok: channel://pecl.php.net/memcache-2.2.6
configuration option "php_ini" is not set to php.ini location
You should add "extension=memcache.so" to php.ini

phpcms v9中使用memcache

phpcms v9强大倒是一说,一些内置的缓存配置方法却没有明确的教程,比如memcache类。
phpcms已经内置了这个缓存,但一直不知道如何启用。

折腾了一晚,想把phpcms的setcache和getcache方法,配置成可以动态切换缓存类型,类型于ThinkPHP的机制。

最后无奈发现phpcms默认开发好像全是使用文件进行存储。
于是,只能在自己需要的地方加上memcache或者redis了,内核要改的话,也忒麻烦了。

配置文件:
cache/configs/cache.php

<?php

return array (
	'file1' => array (
		'type' => 'file',
		'debug' => true,
		'pconnect' => 0,
		'autoconnect' => 0
		),
	'memcache' => array (
		'hostname' => '192.168.0.106',
		'port' => 11211,
		'timeout' => 3600,
		'type' => 'memcache',
		'debug' => true,
		'pconnect' => 0,
		'autoconnect' => 0
	),
	'redis' => array (
		'hostname' => '192.168.0.106',
		'port' => 6379,
		'timeout' => 0,
		'type' => 'redis',
		'debug' => true,
		'pconnect' => 0,
		'autoconnect' => 0
	)
);

?>

文件配置文件的格式上看,和TP机乎一样,但不支持动态切换。

在需要的地方这样写,这里封装了一个获取记录的方法:

/**
 * 调用一个应用详情
 */
function appdetail($appid, $ttl=0)
{
	if(FALSE == is_int($appid)) return FALSE;
		
	$cache_type = 'memcache';
	$cache_name = sprintf(&quot;app_detail_id_%d&quot;, $appid);

	$cache_config = pc_base::load_config('cache');
	
	/* 系统是否支持 */
	$cache_support = !empty($cache_config[$cache_type]) &amp;&amp; class_exists($cache_type);

	if($cache_support)
	{
		$memcache = cache_factory::get_instance($cache_config)->get_cache('memcache');
		$app = $memcache->get($cache_name);
		$app = unserialize($app);
	}else{
		$app = getcache($cache_name);
	}
	
	if($app === false)
	{
		$db = pc_base::load_model('apps_model');
		$app = $db->get_one(array(&quot;id&quot;=>$appid), &quot;id,name&quot;);

		if($cache_support)
		{
			$memcache = cache_factory::get_instance($cache_config)->get_cache('memcache');
			$memcache->set($cache_name, serialize($app), $ttl);
		}else{
			setcache($cache_name, $app, '', $ttl);
		}
	}

	return $app;
}

大约的功能是检测系统是否支持memcache类,支持的话就直接使用memcache,如果不支持,就使用PHPCMS自带的缓存方法。

继续深入折腾setcache,看看是不是我的理解有误

周末在家折腾了一天,慢慢把PHPCMS的MVC和模板标签pc_tag给做熟了,可以肯定的下结论就是:
PHPCMS会把所有进入模板层的数据,进行数据缓存,比如content_tag.class.php中所有的方法,产生的数据还是会被再一次缓存到文件中。

我使用A机产生memcache的数据memcache_A1,使用PHPCMS调用A1以后,会在PHPCMS硬盘上产生PHPCMS_A1,当我的memcache_A1发生改变时,PHPCMS_A1读取的还是PHPCMS_A1这个缓存。
解决方是在pc_tag中,将缓存设置为0,则可以在后端使用其它缓存工具!

Memcache IN ThinkPHP

ThinkPHP中启用Memcache缓存是比较简单的。

首先导入一下扩展缓存类,在TP的扩展完整包中,然后在项目配置文件config.php添加以下配置信息。

其中,Memcache默认端口是11211

设置缓存为Memcache
'DATA_CACHE_TYPE' => 'Memcache',
'MEMCACHE_HOST'   =>  'tcp://127.0.0.1:11211',
'DATA_CACHE_TIME' => '3600',

方法直接使用S函数即可。

当然,也可以清除S中的所有缓存

$cache  = Cache::getInstance();
$cache ->clear();

PHP+Memcache使用入门中文版

这段时间做秒杀程序中,为静态缓存和Mysql的并发数苦恼不已,现在只能动用内存缓存来解决!

以下是一段PHP+Memcache的缓存+读取过程,一看,有点类似于PHP的SESSION保存方法,使用起来也非常简单。

<?php
//连接
$mem = new Memcache;
$mem->connect("127.0.01",  11211);

//保存数据
$mem->set('key1', 'This is first value', 0, 60);
$val = $mem->get('key1');
echo "Get key1 value: " . $val ."<br />";

//替换数据
$mem->replace('key1', 'This is replace value', 0, 60);
$val = $mem->get('key1');
echo "Get key1 value: " . $val . "<br />";

//保存数组
$arr = array('aaa', 'bbb', 'ccc', 'ddd');
$mem->set('key2', $arr, 0, 60);
$val2 = $mem->get('key2');
echo "Get key2 value: ";
print_r($val2);
echo "<br />";

//删除数据
$mem->delete('key1');
$val = $mem->get('key1');
echo "Get key1 value: " . $val . "<br />";

//清除所有数据
$mem->flush();
$val2 = $mem->get('key2');
echo "Get key2 value: ";
print_r($val2);
echo "<br />";

//关闭连接
$mem->close();
?>

以下就是一些中文说明了,如果你还没看懂这是么东西,可以往下看。 继续阅读PHP+Memcache使用入门中文版

Memcache For Windows安装

Memcache在Linux下安装资料挺多,本人的开发环境以WAMP为主,所以备注下WIN32下的安装配置方法,外带一点Zend Studio下的代码提示方法。

Windows下的Memcache安装:
1. 下载memcache的windows稳定版,解压放某个盘下面,比如在c:\memcached
2. 在终端(也即cmd命令界面)下输入 ‘c:\memcached\memcached.exe -d install’ 安装
3. 再输入: ‘c:\memcached\memcached.exe -d start’ 启动。NOTE: 以后memcached将作为windows的一个服务每次开机时自动启动。这样服务器端已经安装完毕了。
4.下载php_memcache.dll,请自己查找对应的php版本的文件
5. 在C:\winnt\php.ini 加入一行 ‘extension=php_memcache.dll’
6.重新启动Apache,然后查看一下phpinfo,如果有memcache,那么就说明安装成功!

memcached的基本设置:

-p 监听的端口
-l 连接的IP地址, 默认是本机
-d start 启动memcached服务
-d restart 重起memcached服务
-d stop|shutdown 关闭正在运行的memcached服务
-d install 安装memcached服务
-d uninstall 卸载memcached服务
-u 以的身份运行 (仅在以root运行的时候有效)
-m 最大内存使用,单位MB。默认64MB
-M 内存耗尽时返回错误,而不是删除项
-c 最大同时连接数,默认是1024
-f 块大小增长因子,默认是1.25
-n 最小分配空间,key+value+flags默认是48
-h 显示帮助

Memcache环境测试:
运行下面的php文件,如果有输出This is a test!,就表示环境搭建成功。开始领略Memcache的魅力把!

<?php
$mem = new Memcache;
$mem->connect(”127.0.0.1″, 11211);
$mem->set(’key’, ‘This is a test!’, 0, 60);
$val = $mem->get(’key’);
echo $val;
?>