我想知道有没有人发现apc_exists()有任何奇怪的行为,当它与apc_add()或apc_store()一起使用时,会导致整个WAMP服务器挂起?经过长时间的“调试”和最小化问题后,我最终得到了导致我的WAMP崩溃的以下代码。
据我所知,它需要1个apc_exists()和2个apc_add()访问不同的密钥。因此,这听起来像是一个死锁问题,我在chrome中运行这个脚本,然后粉碎F5-key,直到我得到rand-thingy发生了两次。在那个时候或者第一次,它通常会挂起来。
<?php
$result = "asdfioasdjfoasdjf";
if(apc_exists("asdf")) {
echo("#1<br/>");
apc_add("launcher", $result, 1);
} else {
echo("#2<br/>");
$result = "asdfasdfasdf";
apc_add("launcher", $result, 10);
}
if(rand(0,100) < 4) {
echo("#stored data!<br/>");
apc_add("asdf", "2130130", 1);
}
?>我的系统/设置:
Windows 7 64位
WAMP 2.2d 32位
PHP版本5.3.10
apc版本3.1.9 | $Revision: 325040 $
我是不是在代码中做错了什么?这是与windows / wamp相关的,还是在其他环境和php/apc版本中存在?在上面的例子中,如果我用apc_fetch()替换apc_exists(),系统不会崩溃,有人知道为什么吗?
发布于 2012-06-04 00:18:35
我相信我找到了原因。这一切都归结为,把answer放在这里,所以:
首先,重要的是要知道,如果一个人试图存储一个已经存在于特定TTL的键,而ttl还没有通过,那么将创建一个新的条目;如果该键是相同的,在内部将有两个相同键的条目。
其次,APC可能失败(未命中)。即使没有明显的原因。为什么?APC的创建显然更看重速度而不是一致性,这意味着当APC驱动程序忙于做一些清理工作时,它将简单地返回NULL,而不是等待完成,即使数据已经存在。它的详细版本在这里:http://phpadvent.org/2010/share-and-enjoy-by-gopal-vijayaraghavan
那么在问题中提到的特定情况下发生了什么?每次请求之间的时间间隔小于1秒,即密钥的指定TTL,因此如果您尝试将密钥存储在此处,则可能会发生重复。“但是,它使用的是apc_add,难道不应该保证只有在密钥不存在的情况下才存储它吗?”显然不是:)这是导致死锁是随机的:有时apc_add会像你所期望的那样工作,另一些它“遗漏”,也就是说,apc_add无法理解存在另一个现有的密钥,即使它在那里。如果是TTL=0,这可能不是问题,因为在这种情况下,密钥只是被覆盖,但在问题的特定情况下,它将存储一个副本,这是由于错误地找不到密钥,并且密钥具有尚未通过的TTL。
因为现在有两个条目在内部具有相同的密钥,所以当使用apc_exists时,它会被混淆并挂起。
要点:不要在APC上存储标志,并且总是准备好一个备用用例,以防它“遗漏”。当APC仅用于存储其他地方存在的东西(即文件或数据库条目)的副本时,APC似乎工作得最好
发布于 2013-02-21 00:22:41
我相信没有明确提到,但只有在apc_exists函数中才会发生死锁。apc_fetch似乎没有遇到任何死锁。我发现为apc_add更改apc_store对死锁没有影响,这两个函数都会发生死锁。
使用apc_fetch的exists检查可能如下所示:
public function has($key) {
apc_fetch($key, $exists);
return $exists;
}https://stackoverflow.com/questions/10494744
复制相似问题