过期时间的最大值(无需像 0 秒那样担心必要时的删除)是 2,592,000 秒(30 天)。
指定超过该值的过期值将返回 false,但不会抛出错误,因此很容易错过。
(PECL memcache >= 0.2.0)
Memcache::set — 在服务器上存储数据
Memcache::set() 将项目 var
与 key
一起存储在 memcached 服务器上。参数 expire
是以秒为单位的过期时间。如果为 0,则该项目永远不会过期(但 memcached 服务器不保证该项目始终存储,它可能会从缓存中删除以腾出空间以供其他项目使用)。如果您想使用动态压缩(使用 zlib),则可以使用 MEMCACHE_COMPRESSED
常量作为 flag
值。
您也可以使用 memcache_set() 函数。注意:
请记住,资源变量(例如文件和连接描述符)不能存储在缓存中,因为它们无法在序列化状态下得到充分表示。
key
将与该项目关联的键。
var
要存储的变量。字符串和整数按原样存储,其他类型则以序列化形式存储。
flag
使用 MEMCACHE_COMPRESSED
以压缩形式存储该项目(使用 zlib)。
expire
项目的过期时间。如果它等于零,则该项目将永远不会过期。您也可以使用 Unix 时间戳或从当前时间开始的秒数,但在后一种情况下,秒数不能超过 2592000(30 天)。
范例 #1 Memcache::set() 范例
<?php
/* 过程式 API */
/* 连接到 memcached 服务器 */
$memcache_obj = memcache_connect('memcache_host', 11211);
/*
设置键为 'var_key' 的项目的 value
使用 0 作为 flag 值,不使用压缩
过期时间为 30 秒
*/
memcache_set($memcache_obj, 'var_key', 'some variable', 0, 30);
echo memcache_get($memcache_obj, 'var_key');
?>
范例 #2 Memcache::set() 范例
<?php
/* OO API */
$memcache_obj = new Memcache;
/* 连接到 memcached 服务器 */
$memcache_obj->connect('memcache_host', 11211);
/*
设置键为 'var_key' 的项目的 value,使用动态压缩
过期时间为 50 秒
*/
$memcache_obj->set('var_key', 'some really big variable', MEMCACHE_COMPRESSED, 50);
echo $memcache_obj->get('var_key');
?>
过期时间的最大值(无需像 0 秒那样担心必要时的删除)是 2,592,000 秒(30 天)。
指定超过该值的过期值将返回 false,但不会抛出错误,因此很容易错过。
这只是关于 memcache 的两件可能不太清楚的小事,即键和数据大小的限制以及 memcache 协议中标志的行为。
* 键的最大大小为 250,任何更大的键都会被截断。数据也有 (1MB - 42 字节) 的限制。
* 在 memcache 协议中,有一个 16 位,在更新的版本中为 32 位的标志,您可以将其设置为任何值,因为 memcache 不会对标志进行任何操作。PHP API 不允许您获取标志,因为 PHP 将标志用于 PHP 自己的用途,例如“MEMCACHE_COMPRESSED”,我决定测试一下它是否在做些什么,因为它不是 memcache 协议的一部分。
<?php
$memcache = new Memcache();
$memcache->connect("127.0.0.1", 11211);
// 由于 memcache 将键截断为 250 字节,因此 "250 个 a" 和 "251 个 a" 都将在缓存中找到该键
echo "*** 键截断测试 ***<br>";
echo "设置 251: " . ($memcache->set(str_repeat("a", 251), "value", 0, 1) ? "t" : "f") . "<br>";
echo "获取 249: " . (($ret = $memcache->get(str_repeat("a", 249))) !== false ? "'$ret'" : "f") . "<br>";
echo "获取 250: " . (($ret = $memcache->get(str_repeat("a", 250))) !== false ? "'$ret'" : "f") . "<br>";
echo "获取 251: " . (($ret = $memcache->get(str_repeat("a", 251))) !== false ? "'$ret'" : "f") . "<br>";
echo "删除: " . ($memcache->delete(str_repeat("a", 250)) ? "t" : "f") . "<br><br>";
echo "*** 压缩值测试 ***<br>";
echo "设置 1024*1024-42: " . ($memcache->set("test", str_repeat("a", 1024*1024-42), 0, 1) ? "t" : "f") . "<br>";
echo "设置 1024*1024-41: " . ($memcache->set("test", str_repeat("a", 1024*1024-41), 0, 1) ? "t" : "f") . "<br>";
echo "设置 1024*1024 压缩: " . ($memcache->set("test", str_repeat("a", 1024*1024), MEMCACHE_COMPRESSED, 1) ? "t" : "f") . "<br>";
echo "删除: " . ($memcache->delete("test") ? "t" : "f") . "<br>";
$memcache->close();
?>
输出
*** 键截断测试 ***
设置 251: t
获取 249: f
获取 250: 'value'
获取 251: 'value'
删除: t
*** 压缩值测试 ***
设置 1024*1024-42: t
设置 1024*1024-41: f
设置 1024*1024 压缩: t
删除: t
对同一个键多次使用 set 似乎会产生意想不到的结果——它不像“替换”,而是似乎对同一个键“设置”了多个值。“get”可能会返回任何一个值。
这是在多服务器设置中测试的——如果只使用一台服务器,行为可能会有所不同。
解决方法是结合使用 replace 和 set
<?php
$result = $memcache->replace( $key, $var );
if( $result == false )
{
$result = $memcache->set( $key, $var );
}
?>
我在存储少量数据(如整数)时遇到了使用 MEMCACHE_COMPRESSED 标记的问题。
例如。
<?php
Memcache::set('integer', 123456, MEMCACHE_COMPRESSED);
// 将返回 true
Memcache::get('integer');
// 将返回 false
?>
当我为较小的值删除 MEMCACHE_COMPRESSED 标记时,这个问题就消失了。
如果您有兴趣使用压缩,请注意,至少对于 PHP 版本 5.3.2 和 Memcache 版本 3.0.4,当检索值是数字或布尔类型的键时,PHP 会抛出以下通知
消息:MemcachePool::get(): 无法解压缩数据
解决方法是在将变量设置为 Memcache 或添加到 Memcache 之前测试您的变量类型,甚至将其强制转换为字符串。
<?php
$key = 'mc_key';
$value = 12345;
$compress = is_bool($value) || is_int($value) || is_float($value) ? false : MEMCACHE_COMPRESSED;
$mc= new Memcache;
$mc->connect('localhost', 11211);
$mc->set($key, $value, $compress);
echo $mc->get($key);
// 另一种方法是将变量强制转换
$value = is_scalar($value) ? (string)$value : $value;
$mc->set($key, $value, MEMCACHE_COMPRESSED);
?>
这里关于 replace 和 set 的说明在我的测试中不再有效。您可以根据需要多次调用 set 在同一个键上,并可靠地获取最后写入的值。我在 3 个 memcache 节点上对 10000 个键进行了测试。
如果您收到以下消息
"标志数组的最低两位字节保留供 pecl/memcache 内部使用"
那么请尝试以下操作
a) 尝试使用 Memcached 而不是 Memcache。
b) 切换压缩值
$memcache->set($key,$value,MEMCACHE_COMPRESSED)
或者
$memcache->set($key,$value,0)
如果您想缓存动态生成的图像,您可以执行以下操作
<?php
ob_start();
imagepng($image);
$memcache->set("my_image", ob_get_contents(), false, $cache_time);
ob_end_clean();
?>
然后您可以像访问简单变量一样访问缓存的图像
<?php $my_image = $memcache->get("my_image"); ?>
简而言之,您必须缓冲输出
为了纠正一些事情
最大过期时间:RTFM,这里有说明。
最大数据量:几乎无限,只要您的服务器能够承受。
速度和节奏
嗯,这是另一件事。我们有一些数据记录,出于应用程序原因,必须保存在内存中。由于数据量很大,而且变化频率不高,我们考虑将数据缓存到 memcache 中,而不是每次都从 DB 中检索数据。
这不是一个普遍的建议,也不是任何质量声明,但我们对序列化数组(50 MB)进行了一些测试,压缩和未压缩,结果发现,在我们的特定情况下,memcache 比 DB(mySql)慢得多。
一般来说,无法预测 memcache 在某些情况下如何运行,但始终需要在开始将内容部署到实时系统之前进行一些测试和基准测试。
尽管进行了上述测试,我们仍然使用 memcache 进行会话缓存,而不是使用文件系统,因为还有一些其他因素需要考虑,而且数据量始终很小(几 KB)。
int 的最低字节保留用于 pecl/memcache 内部使用(例如,用于指示压缩和序列化状态)。