7

我想知道是否有人发现与或apc_exists()一起使用时导致整个 WAMP 服务器挂起的任何奇怪行为?经过长时间的“调试”和最小化问题后,我最终得到了导致我的 WAMP 崩溃的以下代码。apc_add()apc_store()

据我所知,它需要 1apc_exists()和 2apc_add()访问不同的密钥。[因此听起来像是一个死锁问题] 我在 chrome 中运行这个脚本,然后按下 F5 键,直到我让 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 64bit
WAMP 2.2d 32bit
PHP 版本 5.3.10
apc 版本 3.1.9 | $修订:325040 $

我在代码中做错了吗?这与 windows / wamp 有关还是存在于其他环境和 php/apc-versions 中?在上述情况下,如果我替换apc_exists()apc_fetch(),系统不会崩溃,有人知道为什么吗?

4

2 回答 2

6

我相信我找到了原因。这一切都归结为这个很好的答案

首先,重要的是要知道,如果一个人试图存储一个已经存在的具有特定 TTL 的密钥,并且该 ttl 尚未通过,则会创建一个新条目;密钥是否相同并不重要,内部有两个相同密钥的条目。

其次,APC 可能会失败(未命中)。即使没有明显的原因。为什么?APC 显然是为了速度而不是一致性而创建的,这意味着当 APC 驱动程序忙于进行一些清理时,即使数据存在,它也会简单地返回 NULL 而不是等到它完成。这个的长版本在这里: http: //ppadvent.org/2010/share-and-enjoy-by-gopal-vijayaraghavan

那么问题中提到的具体情况是怎么回事?每个请求之间的时间短于 1 秒,即密钥的指定 TTL,因此如果您尝试将密钥存储在此处,可能会发生重复。“但是,它正在使用 apc_add,那不应该保证密钥仅在它不存在时才被存储吗?” 显然不是 :) 这就是导致死锁随机的原因:有时 apc_add 会按您的预期工作,而其他一些会“错过”,也就是说,即使存在另一个密钥,apc_add 也无法理解。如果 TTL=0,这可能不是问题,因为在这种情况下,密钥会被简单地覆盖,但在问题的特定情况下,

由于现在内部有两个具有相同键的条目,所以当使用 apc_exists 时,它会混淆并挂起。

要点:不要在 APC 上存储标志,并始终准备一个备用案例以防它“错过”。APC 似乎在仅用于存储其他地方存在的东西的副本时效果最好(即文件或数据库条目)

于 2012-06-03T16:18:34.780 回答
1

我相信它没有明确提到,但死锁发生在apc_exists函数中。apc_fetch似乎没有遇到任何僵局。我发现更改apc_storeforapc_add对死锁没有影响,它们发生在两个函数中。

使用的存在检查apc_fetch可能如下所示:

public function has($key) {
    apc_fetch($key, $exists);
    return $exists;
}
于 2013-02-20T16:22:40.760 回答