2010-03-01 15 views
7

Qual è il modo migliore per scrivere su file in un'applicazione php di grandi dimensioni. Diciamo che ci sono molte scritture necessarie al secondo. Come è il modo migliore per farlo.Come scrivere su file in un'applicazione php di grandi dimensioni (più domande)

Posso semplicemente aprire il file e aggiungere i dati. O dovrei aprire, bloccare, scrivere e sbloccare.

Ciò che accadrà sul file viene elaborato e altri dati devono essere scritti. Questa attività andrà persa o verrà salvata. e se questo sarà salvato, si fermerà l'applicazione.

Se sei stato, grazie per aver letto!

risposta

6

Ho un'applicazione multithread ad alte prestazioni, in cui tutti i thread stanno scrivendo (aggiungendo) al singolo file di registro. So-far non ha notato alcun problema con questo, ogni thread scrive più volte al secondo e nulla si perde. Penso che l'aggiunta di file enormi non dovrebbe costituire un problema. Ma se si desidera modificare già contenuti esistenti, in particolare con la concorrenza - vorrei andare con bloccaggio, altrimenti gran casino può succedere ...

+0

+1. Ricevo voci sovrapposte nel mio registro di accesso di Apache ogni giorno, quindi a carico elevato si verifica sicuramente una certa perdita. Ma per un file di registro, le poche righe che vengono storpiate non contano, e certamente non valgono il sovraccarico del blocco dei file. –

+0

@Laimoncijus, vuoi dire che gli appendi sono atomici? – Pacerier

4

Se la concorrenza è un problema, è necessario utilizzare i database.

+2

Sto scrivendo su un file di registro. La scrittura nel database è già pesante, quindi per il file di registro vorrei solo scrivere su file. –

+0

Anche i file sono concomitanti. – Pacerier

-3

Se avete solo bisogno di aggiungere dati, PHP dovrebbe andare bene con quello come filesystem dovrebbe prendersi cura di accodamento simultanei.

+1

I file system standard di Linux sicuramente fanno * non * "attenzione" alle appline simultanee. Per un semplice esempio del perché, immagina questo: due processi aprono lo stesso file in millisecondi l'uno dall'altro e aggiungono un gig di dati a 100 meg al secondo, ovvero un tempo di scrittura di 10 secondi per ogni processo. In che modo il filesystem garantisce che le scritture non si sovrappongano? Dovrebbe bufferizzare i dati dal secondo processo fino al completamento del primo processo? –

+1

beh, dato che hai usato un esempio assolutamente assurdo, dirò solo questo: PHP non è in grado di aggiungere 100 meg al secondo, né può elaborare quei dati. anche se puoi essere corretto su situazioni ipotetiche come questa, la realtà è una cosa diversa e come qualcuno sopra descritto, aggiungendo solo funziona. mangia quello. – dusoft

+0

Inserito un esempio semplice e reale che mostra più applet simultanei che si scontrano l'un l'altro. http://stackoverflow.com/questions/2358818/how-to-write-to-file-in-large-php-applicationmultiple-questions/2360472#2360472 –

9

Ecco un semplice esempio che mette in evidenza il pericolo di wites simultanei:

<?php 
for($i = 0; $i < 100; $i++) { 
$pid = pcntl_fork(); 
//only spawn more children if we're not a child ourselves 
if(!$pid) 
    break; 
} 

$fh = fopen('test.txt', 'a'); 

//The following is a simple attempt to get multiple threads to start at the same time. 
$until = round(ceil(time()/10.0) * 10); 
echo "Sleeping until $until\n"; 
time_sleep_until($until); 

$myPid = posix_getpid(); 
//create a line starting with pid, followed by 10,000 copies of 
//a "random" char based on pid. 
$line = $myPid . str_repeat(chr(ord('A')+$myPid%25), 10000) . "\n"; 
for($i = 0; $i < 1; $i++) { 
    fwrite($fh, $line); 
} 

fclose($fh); 

echo "done\n"; 

Se le appende erano sicure, dovresti ottenere un file con 100 righe, di cui circa 10.000 caratteri lunghi e che inizia con un numero intero. E a volte, quando esegui questo script, è esattamente quello che otterrai. A volte, alcune appendici entrano in conflitto, e tuttavia si romperanno.

Si possono trovare le linee corrotte con grep '^[^0-9]' test.txt

Questo perché file append is only atomic if:

  1. si effettua una singola fwrite() chiamata
  2. e che fwrite() è più piccolo di PIPE_BUF (da qualche parte intorno 1 -4k)
  3. e si scrive su un filesystem completamente POSIX compatibile

Se si effettua più di una singola chiamata a fwrite durante l'append del log, o si scrive più di circa 4k, tutte le scommesse sono disattivate.

Ora, se questo è importante o meno: stai bene con alcune linee danneggiate nel tuo log sotto carico pesante? Onestamente, la maggior parte delle volte questo è perfettamente accettabile, ed è possibile evitare il sovraccarico del blocco dei file.

+1

+1 Punto ben fatto signore –

1

Se si stanno solo scrivendo i registri, forse è necessario dare un'occhiata alla funzione syslog, poiché syslog fornisce un'API. Dovresti anche delegare le scritture a un backend dedicato e svolgere il lavoro in una mania asincrona?

1

Questi sono i miei 2p.

A meno che non sia necessario un file univoco per un motivo specifico, eviterei di aggiungere tutto a un file enorme. Invece, vorrei avvolgere il file in base al tempo e alle dimensioni. Per questo potrebbe essere definito un paio di parametri di configurazione (wrap_time e wrap_size).

Inoltre, probabilmente introdurrei il buffering per evitare di attendere l'operazione di scrittura da completare.

Probabilmente PHP non è la lingua più adatta per questo tipo di operazioni, ma potrebbe essere ancora possibile.

Problemi correlati