2011-04-09 32 views
17

¿Es posible compartir variables y matrices entre todos los procesos de PHP sin duplicarlos?Compartir variables/memoria entre todos los procesos de PHP

Usando memcached, creo que PHP duplica la memoria utilizada:
$array = $memcache->get('array');
$ matriz contendrá una copia de memcached.

Así que mi idea es que podría haber una variable estática que ya estaba definida y compartida entre todos los procesos.

+1

es su gama tan grande? –

+0

Sí. ¿Puedes agregar un poco más de contexto? ¿Qué hay de almacenar los datos en una base de datos y recuperar solo los bits que necesita en el script actual? –

+0

esto generalmente se resuelve almacenando los datos en una base de datos y obteniendo solo lo que se necesita. –

Respuesta

4

Por defecto simplemente no es posible. Cada solución siempre copiará el contenido en el alcance actual, porque si no, no hay forma de acceder a él.

No sé, qué es exactamente lo que quiero hacer, pero tal vez puede hacer eso "afuera", por ejemplo, como un trabajo gearman, y luego simplemente ver los resultados del proceso, en lugar de toda la matriz.

También puede pensar en dividir la matriz "grande" en secciones y luego siempre recuperar la parte que necesita actualmente de una APC o memoria.

+5

Bien, finalmente una respuesta útil: "no es posible". Prefiero la sinceridad más que insultos o sarcasmos. Gracias, esta es mi respuesta aceptada. – Nuno

+0

En cuanto a su 3er párrafo, uso ese método ya para otras cosas. Mi preocupación es cuando realmente no sé lo que está sucediendo, como dije en mi pregunta. – Nuno

+2

@Nuno no seas tan susceptible. Nadie te insultó. Si la respuesta no fue útil para usted, intente mejorar su pregunta en lugar de sentirse herido. –

0

Editar:
Probablemente esté utilizando la memoria compartida de forma incorrecta.
Su memoria compartida en sí misma es dicha matriz. Por lo tanto, debe almacenar cadenas de varios idiomas separadas directamente en la memoria compartida, no en una gran matriz.
y luego solo tirar de las cadenas, requeridas en una página en particular.
eso es todo.

En general, para procesar algunos datos, un programa tiene que "duplicarlos", almacenándolos en una variable.
Para eso están las variables: almacenar (o "duplicar") algunos datos externos.
Por ejemplo, si tiene alguna información de usuario en su base de datos, para mostrar un nombre de usuario en una página web debe "duplicar" esta información, primero debe almacenarla en la variable PHP.
Y así sucesivamente.

Usted es el primero que piensa que tal enfoque necesita ser cambiado.

7

Una forma de compartir memoria entre procesos de PHP es instalar un caché de PHP-bytecode como APC. APC se usa principalmente para almacenar el bytecode en un segmento de memoria compartida administrada por el sistema operativo, pero también tiene una API para compartir todo lo que desee entre los procesos (como una versión local de Memcache).

<?php 
    $foobar = array('foo', 'bar'); 
    apc_store('foobar', $foobar); 
?> 

Luego en otra parte:

<?php 
    $foobar = apc_fetch('foobar'); 
    var_dump($foobar); 
?> 

El gran problema con el intercambio de memoria es que se hace muy fácil para los dos procesos de pisar el pie de uno al otro. Así que la memoria compartida es mejor para cosas que no cambian demasiado, como las grandes matrices globales.

+0

Parece lo mismo que Memcached. Gracias por su respuesta, de todos modos :) – Nuno

+1

@NunoPeralta, ¿Qué pasa con 'Shmop'? Vea abajo. – Pacerier

+0

Esto está mal, apc_store etc. no puede compartir memoria entre procesos. Cada proceso asigna su propio segmento de memoria. puede, por ejemplo, no compartir memoria entre php-fpm y php-cli por ese motivo (mientras que el intercambio entre diferentes solicitudes de php-fpm funciona). – bhelm

3

PHP tiene métodos mágicos:

  • __get($property) vamos a implementar el acceso de un $ propiedad sobre un objeto
  • __set($property, $value) vamos a implementar la asignación de un $ propiedad sobre un objeto

PHP puede serializar variables:

  • serialize($variable) devuelve una representación de cadena de la variable
  • unserialize($string) retorna una variable de una cadena

PHP puede manejar archivos, con una gestión de acceso concurrente:

  • fopen($file, 'c+') abre un archivo con opciones de bloqueo de asesoramiento habilitado (le permiten usar rebaño)
  • flock($descriptor, LOCK_SH) toma un bloqueo compartido (para lectura)
  • flock($descriptor, LOCK_EX) toma un correo Bloqueo xclusivo (para escritura)

Por lo tanto, la forma más fácil de compartir un objeto entre aplicaciones es crear una clase que implemente y use todos esos elementos para guardar y restaurar al instante todos sus datos en un archivo.

Una simple aplicación de esa clase podría ser:

class Synchro 
{ 

    private $_file; 

    public function __construct($file) 
    { 
     $this->_file = $file; 
    } 

    public function __get($property) 
    { 
     // File does not exist 
     if (!is_file($this->_file)) 
     { 
      return null; 
     } 

     // Check if file is readable 
     if ((is_file($this->_file)) && (!is_readable($this->_file))) 
     { 
      throw new Exception(sprintf("File '%s' is not readable.", $this->_file)); 
     } 

     // Open file with advisory lock option enabled for reading and writting 
     if (($fd = fopen($this->_file, 'c+')) === false) 
     { 
      throw new Exception(sprintf("Can't open '%s' file.", $this->_file)); 
     } 

     // Request a lock for reading (hangs until lock is granted successfully) 
     if (flock($fd, LOCK_SH) === false) 
     { 
      throw new Exception(sprintf("Can't lock '%s' file for reading.", $this->_file)); 
     } 

     // A hand-made file_get_contents 
     $contents = ''; 
     while (($read = fread($fd, 32 * 1024)) !== '') 
     { 
      $contents .= $read; 
     } 

     // Release shared lock and close file 
     flock($fd, LOCK_UN); 
     fclose($fd); 

     // Restore shared data object and return requested property 
     $object = json_decode($contents); 
     if (property_exists($object, $property)) 
     { 
      return $object->{$property}; 
     } 

     return null; 
    } 

    public function __set($property, $value) 
    { 
     // Check if directory is writable if file does not exist 
     if ((!is_file($this->_file)) && (!is_writable(dirname($this->_file)))) 
     { 
      throw new Exception(sprintf("Directory '%s' does not exist or is not writable.", dirname($this->_file))); 
     } 

     // Check if file is writable if it exists 
     if ((is_file($this->_file)) && (!is_writable($this->_file))) 
     { 
      throw new Exception(sprintf("File '%s' is not writable.", $this->_file)); 
     } 

     // Open file with advisory lock option enabled for reading and writting 
     if (($fd = fopen($this->_file, 'c+')) === false) 
     { 
      throw new Exception(sprintf("Can't open '%s' file.", $this->_file)); 
     } 

     // Request a lock for writting (hangs until lock is granted successfully) 
     if (flock($fd, LOCK_EX) === false) 
     { 
      throw new Exception(sprintf("Can't lock '%s' file for writing.", $this->_file)); 
     } 

     // A hand-made file_get_contents 
     $contents = ''; 
     while (($read = fread($fd, 32 * 1024)) !== '') 
     { 
      $contents .= $read; 
     } 

     // Restore shared data object and set value for desired property 
     if (empty($contents)) 
     { 
      $object = new stdClass(); 
     } 
     else 
     { 
      $object = json_decode($contents); 
     } 
     $object->{$property} = $value; 

     // Go back at the beginning of file 
     rewind($fd); 

     // Truncate file 
     ftruncate($fd, strlen($contents)); 

     // Save shared data object to the file 
     fwrite($fd, json_encode($object)); 

     // Release exclusive lock and close file 
     flock($fd, LOCK_UN); 
     fclose($fd); 

     return $value; 
    } 

} 

Ahora, puede utilizar esta clase como stdClass, pero con una ruta de archivo en la construcción.

$obj = new Synchro("/tmp/test.sync"); 
$obj->hello = 'world'; 

// ... and in another process... 
echo $obj->hello; 

Este ejemplo es, por supuesto, muy simple, se toma cuidado sobre el acceso simultáneo a un archivo, pero no a una variable, en una mejor aplicación que va a utilizar un bloqueo de exclusión mutua similar.

Acabo de empujar esta clase (después de completarla) en github, puedes encontrarla en here.

+3

Has malentendido la pregunta. – Pacerier

+0

me gusta ... usar el archivo es quizás la forma más simple y más segura, ya que no se intenta la memoria del servidor. Creo que es más rápido que pedir una base de datos también. – Meloman

+0

esto no es diferente de usar una base de datos, la idea es compartir variables en la memoria, no en el disco. –

18

Usando Shmop:

shmop es una herramienta fácil de usar conjunto de funciones que permite PHP para leer, escribir , crear y borrar segmentos de memoria compartida Unix.

de: http://www.php.net/manual/en/intro.shmop.php

No se necesitan bibliotecas externas para construir esta extensión.

Las funciones de memoria compartida

  • shmop_close - Cerrar
  • memoria compartida bloque
  • shmop_delete - Borrar la memoria compartida bloque
  • shmop_open - bloque Crear o abrir la memoria compartida
  • shmop_read - Leer datos del bloque de memoria compartida
  • shmop_size - Obtiene el tamaño del segmento de memoria compartida
  • shmop_write - Escribir datos en bloque de memoria compartida

Uso básico

// Create 100 byte shared memory block with system id of 0xff3 
$shm_id = shmop_open(0xff3, "c", 0644, 100); 
if (!$shm_id) { 
    echo "Couldn't create shared memory segment\n"; 
} 

// Get shared memory block's size 
$shm_size = shmop_size($shm_id); 
echo "SHM Block Size: " . $shm_size . " has been created.\n"; 

// Lets write a test string into shared memory 
$shm_bytes_written = shmop_write($shm_id, "my shared memory block", 0); 
if ($shm_bytes_written != strlen("my shared memory block")) { 
    echo "Couldn't write the entire length of data\n"; 
} 

// Now lets read the string back 
$my_string = shmop_read($shm_id, 0, $shm_size); 
if (!$my_string) { 
    echo "Couldn't read from shared memory block\n"; 
} 
echo "The data inside shared memory was: " . $my_string . "\n"; 

//Now lets delete the block and close the shared memory segment 
if (!shmop_delete($shm_id)) { 
    echo "Couldn't mark shared memory block for deletion."; 
} 
shmop_close($shm_id); 
+1

Vea también http://stackoverflow.com/a/8631902/632951 – Pacerier

+1

[Para usar shmop, deberá compilar PHP con el parámetro ** - enable-shmop ** en su línea de configuración.] (Http: // php.net/manual/en/shmop.installation.php) – Pang

Cuestiones relacionadas