2010-03-01 9 views
7

¿Cuál es la mejor manera de escribir en archivos en una aplicación de php grande. Digamos que hay muchas escrituras necesarias por segundo. ¿Cómo es la mejor manera de hacerlo?Cómo escribir en un archivo en la aplicación php grande (preguntas múltiples)

¿Podría simplemente abrir el archivo y anexar los datos? ¿O debería abrir, bloquear, escribir y desbloquear?

¿Qué pasará con el archivo en el que se trabaja y se deben escribir otros datos? Se perderá esta actividad, o se guardará esto. y si esto se guardará, se detendrá la aplicación.

Si has estado, ¡gracias por leer!

Respuesta

6

Tengo una aplicación multi-hilo de alto rendimiento, donde todos los hilos están escribiendo (añadiendo) a un único archivo de registro. Hasta el momento no notó ningún problema con eso, cada hilo escribe varias veces por segundo y no se pierde nada. Creo que agregar un archivo enorme no debería ser un problema. Pero si desea modificar ya el contenido existente, especialmente con la concurrencia - Me gustaría ir con bloqueo, de lo contrario puede suceder gran lío ...

+0

+1. Recibo entradas superpuestas en mi registro de acceso de apache todos los días, por lo que a una carga alta definitivamente se produce una pérdida. Pero para un archivo de registro, las pocas filas que se rompen realmente no importan, y ciertamente no valen la sobrecarga del bloqueo de archivos. –

+0

@Laimoncijus, ¿Quieres decir que los añadidos son atómicos? – Pacerier

4

Si la concurrencia es un problema, realmente debería utilizar las bases de datos.

+2

Escribo en un archivo de registro. La escritura en la base de datos ya es pesada, por lo que para el archivo de registro me gustaría simplemente escribir en el archivo. –

+0

Los archivos están destinados a ser concurrentes también. – Pacerier

-3

Si sólo tiene que añadir datos, PHP debe estar bien con eso como sistema de archivos debe tener cuidado de APPENDs simultáneas.

+1

Los sistemas de archivos linux estándar ciertamente no * "se encargan" de adjuntos simultáneos. Para un ejemplo simple de por qué ocurre esto, imagine esto: dos procesos abren el mismo archivo en milisegundos entre sí y añaden un registro de datos a 100 meg por segundo, lo que significa un tiempo de escritura de 10 segundos para cada proceso. ¿Cómo garantizaría el sistema de archivos que las escrituras no se superpongan? ¿Se supone que almacenará los datos del segundo proceso hasta que se complete el primer? –

+1

bueno, ya que tienes un ejemplo absolutamente absurdo, solo diré esto: PHP no puede agregar 100 megas por segundo, ni puede procesar esos datos. Sin embargo, puede estar en lo cierto acerca de situaciones hipotéticas como esta, la realidad es algo diferente y, como alguien descrito arriba, anexar simplemente funciona. come eso. – dusoft

+0

Publicó un ejemplo simple y real que muestra múltiples anexos simultáneos que se atan entre sí. http://stackoverflow.com/questions/2358818/how-to-write-to-file-in-large-php-applicationmultiple-questions/2360472#2360472 –

9

Aquí está un ejemplo sencillo que pone de relieve el peligro de wites simultáneas:

<?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"; 

Si los archivos adjuntos son seguros, debe obtener un archivo con 100 líneas, todas las cuales tienen aproximadamente 10 000 caracteres de longitud y comienzan con un número entero. Y a veces, cuando ejecuta este script, eso es exactamente lo que obtendrá. A veces, algunos añadidos entrarán en conflicto, y se destrozarán, sin embargo.

puede encontrar líneas dañados con grep '^[^0-9]' test.txt

Esto se debe a file append is only atomic if:

  1. se hace un solo fwrite() llama a
  2. y que fwrite() es más pequeño que PIPE_BUF (en algún lugar alrededor de 1 -4k)
  3. y escribe en un sistema de archivos totalmente compatible con POSIX

Si hace más de una llamada para escribir durante su registro, o escribe más de 4k, todas las apuestas están desactivadas.

Ahora, en cuanto a si esto importa o no: ¿está de acuerdo con tener algunas líneas corruptas en su registro bajo una gran carga? Honestamente, la mayoría de las veces esto es perfectamente aceptable, y puede evitar la sobrecarga de bloqueo de archivos.

+1

+1 punto bien hecho señor –

1

Si solo está escribiendo registros, tal vez tenga que echar un vistazo a la función syslog, ya que syslog proporciona una API. ¿También debería delegar escrituras en un back-end dedicado y hacer el trabajo en un maneer asincrono?

1

Estos son mis 2p.

A menos que se necesite un archivo único por una razón específica, evitaría anexar todo a un archivo enorme. En cambio, enviaría wrap el archivo por tiempo y dimensión. Se podrían definir un par de parámetros de configuración (wrap_time y wrap_size) para esto.

Además, probablemente introduciría algunos buffering para evitar que se complete la operación de escritura.

Probablemente, PHP no es el lenguaje más adecuado para este tipo de operaciones, pero aún podría ser posible.

Cuestiones relacionadas