2012-05-08 5 views
7

Mi chiedo se qualcuno abbia riscontrato strani comportamenti con apc_exists(), un comportamento che causa l'interruzione dell'intero server WAMP quando viene utilizzato insieme a apc_add() o apc_store()? Dopo una lunga sessione di "debug" e minimizzazione del problema, ho finito con il seguente codice che causa il crash del mio WAMP.Deadlock con apc_exists e apc_add? (apc e PHP)

Per quanto ne so, è necessario 1 apc_exists() e 2 apc_add() accedere a chiavi diverse. [quindi sembra un problema di deadlock] Eseguo questo script in chrome e poi fracassa F5-key fino a quando il rand-thingy non si verifica due volte. A quel tempo o la prima volta di solito si blocca.

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

mio sistema/configurazione:
Windows 7 64bit
WAMP 2.2d 32bit
PHP versione 5.3.10
versione apc 3.1.9 | $ Revisione: 325040 $

Sto facendo qualcosa di sbagliato nel codice? E 'collegato a windows/wamp o esiste in altri ambienti e versioni php/apc? Nel caso precedente, se sostituisco apc_exists() con apc_fetch(), il sistema non si blocca, qualcuno sa perché?

+1

Stesso qui. Sembra che apc_exists + 1 secondo timeout keys = deadlock in alcuni casi casuali. Immagino sia un bug? – Mahn

+0

Beh, in realtà avevo una chiave da 300 secondi, quindi non è correlata all'ora –

+0

Sì, era una delle ipotesi iniziali, ma penso che la risposta qui sotto sia ancora valida; Finché la chiave ha una data di scadenza e non è ancora scaduta, possono verificarsi duplicati interni – Mahn

risposta

5

Credo di aver trovato la causa. Tutto si riduce a questo ben messo answer qui su SO:

In primo luogo, è importante sapere che se si tenta di memorizzare una chiave che esiste già con uno specifico TTL, E il TTL non è ancora passato, un nuovo la voce sarà creata; non importa se la chiave è la stessa, internamente ci sarà essere due voci della stessa chiave.

Secondo, APC può fallire (miss). Anche quando non c'è una ragione apparente per questo. Perché? È stato apparentemente creato APC che favorisce la velocità rispetto alla coerenza, il che significa che quando il driver APC è impegnato a fare un po 'di pulizia, restituirà semplicemente NULL invece di aspettare fino a quando non viene eseguito, anche se i dati esistono. La versione lunga di questo è qui: http://phpadvent.org/2010/share-and-enjoy-by-gopal-vijayaraghavan

Quindi cosa succede nel caso specifico menzionato nella domanda? Il tempo tra ogni richiesta è inferiore a 1 secondo, il TTL specificato delle chiavi, quindi i duplicati possono verificarsi se si tenta di memorizzare la chiave qui. "Ma sta usando apc_add, non dovrebbe garantire che la chiave sia memorizzata solo se non esiste già?" Apparentemente no :) questo è ciò che fa sì che il deadlock sia casuale: a volte apc_add funziona come ci si aspetterebbe, altri mancano, cioè apc_add non riesce a capire che c'è un'altra chiave esistente anche se è presente. Questo è probabilmente non è un problema se il TTL = 0, perché in tal caso la chiave viene semplicemente sovrascritta, ma nel caso specifico della domanda, memorizzerà un duplicato a causa di erroneamente non riuscendo a trovare la chiave AND il chiave che ha un TTL che non è ancora passato.

Poiché ora sono presenti due voci con la stessa chiave internamente, quando viene utilizzato apc_exists, viene confuso e sospeso.

Takeaways: non memorizza i flag su APC e sempre un caso di riserva preparato nel caso in cui "manchi". APC sembra funzionare meglio quando viene utilizzato solo per memorizzare copie di roba che esiste altrove (ad esempio un file o una voce di database)

+1

Questo è un buon consiglio e tutto, ma non sono sicuro che risponda alla domanda in questione - il codice di esempio sopra è tutto in linea retta ; non c'è niente lì che dovrebbe causare un blocco. – duskwuff

+1

Corretto, il punto è, non c'è nulla di sbagliato nel codice OP, quello che sta vivendo è come funziona APC. – Mahn

+2

Arrestare l'interprete è "come funziona APC"? Penso di no. Sono abbastanza sicuro che questo è un bug in APC e dovrebbe essere segnalato di conseguenza. – duskwuff

1

credo che non è menzionato in modo esplicito, ma le situazioni di stallo si verificano solo con la funzione apc_exists.apc_fetch non sembra soffrire di alcun deadlock. Ho notato che la modifica di per non ha alcun effetto sui deadlock, si verificano per entrambe le funzioni.

Un esiste controllo utilizzando apc_fetch potrebbe apparire come:

public function has($key) { 
    apc_fetch($key, $exists); 
    return $exists; 
}