7

誰かがapc_exists()、またはと一緒に使用したときにWAMPサーバー全体がハングする原因となる奇妙な動作を見つけたのではないapc_add()かと思いapc_store()ます。「デバッグ」と問題の最小化の長いセッションの後、私はWAMPをクラッシュさせる次のコードに行き着きました。

私が知る限り、1apc_exists()と2がapc_add()異なるキーにアクセスする必要があります。[したがって、デッドロックの問題のように聞こえます]このスクリプトをクロムで実行してから、ランドが2回発生するまで、F5キーをスマッシュします。その時または初めてそれは通常ハングします。

<?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);
}
?>

私のシステム/セットアップ:
Windows764ビット
WAMP2.2d32ビット
PHPバージョン
5.3.10apcバージョン3.1.9| $改訂:325040 $

コードで何か間違ったことをしていますか?これはwindows/wampに関連していますか、それとも他の環境やphp / apc-versionsに存在しますか?上記の場合、に置き換えapc_exists()apc_fetch()もシステムはクラッシュしませんが、その理由を誰かが知っていますか?

4

2 に答える 2

6

原因を見つけたと思います。それはすべて、SOに関するこの適切な答えに帰着します:

まず、特定のTTLですでに存在するキーを保存しようとして、ttlがまだ渡されていない場合、新しいエントリが作成されることを知っておくことが重要です。キーが同じであるかどうかは関係ありません。内部的に同じキーの2つのエントリがあります。

第二に、APCは失敗する(ミスする)可能性があります。明確な理由がない場合でも。なんで?APCは、一貫性よりも速度を優先して作成されたようです。つまり、APCドライバーがクリーンアウトの実行でビジー状態の場合、データが存在していても、完了するまで待機するのではなく、単にNULLを返します。これの長いバージョンはここにあります:http://phpadvent.org/2010/share-and-enjoy-by-gopal-vijayaraghavan

では、質問で言及された特定のケースで何が起こっているのでしょうか?各リクエスト間の時間は、キーの指定されたTTLである1秒より短いため、ここにキーを保存しようとすると重複が発生する可能性があります。「しかし、apc_addを使用しているので、キーがまだ存在しない場合にのみキーが保存されることを保証するべきではありませんか?」明らかにそうではありません:)これがデッドロックの原因です。apc_addが期待どおりに機能する場合もあれば、「欠落」している場合もあります。つまり、apc_addは、別の既存のキーが存在する場合でもそれを理解できません。TTL = 0の場合、これはおそらく問題ではありません。そのような場合、キーは単に上書きされるためですが、質問の特定のケースでは、

内部的に同じキーを持つ2つのエントリがあるため、apc_existsを使用すると、混乱してハングします。

要点:APCにフラグを保存しないでください。また、「失敗」した場合に備えて、フォールバックケースを常に用意してください。APCは、他の場所に存在するもの(つまり、ファイルまたはデータベースエントリ)のコピーを保存するためにのみ使用される場合に最適に機能するようです。

于 2012-06-03T16:18:34.780 に答える
1

明示的には言及されていないと思いますが、デッドロックは関数でのみ発生しapc_existsます。apc_fetchデッドロックに苦しんでいないようです。apc_storeforを変更しapc_addてもデッドロックには影響がなく、両方の関数で発生することがわかりました。

を使用した既存のチェックは次のapc_fetchようになります。

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