Подтвердить что ты не робот

Обмен переменными/памятью между всеми процессами PHP

Можно ли обмениваться переменными и массивами между всеми процессами PHP без дублирования их?

Используя memcached, я думаю, что PHP дублирует используемую память:
$array = $memcache->get('array');
$ array будет содержать копию из memcached.

Итак, моя идея: может существовать переменная static, которая уже была определена и разделена между всеми процессами.

4b9b3361

Ответ 1

По умолчанию его просто невозможно. Каждое решение всегда будет копировать содержимое в текущую область, потому что, если нет, нет доступа к нему.

Я не знаю, что именно нужно делать, но, возможно, вы можете сделать это "снаружи", например, как gearman, а затем просто поймать результаты процесса, а не весь массив.

Вы также можете подумать о разделении "большого" массива на срезы, а затем всегда извлекать нужную вам часть из apc или memcached.

Ответ 2

Использование Shmop:

Shmop - это простой в использовании набор функций, который позволяет PHP читать, писать, создавать и удалять сегменты разделяемой памяти Unix.

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

Для создания этого расширения внешние библиотеки не нужны.

Общие функции памяти

  • shmop_close - Закрыть
  • блок разделяемой памяти
  • shmop_delete - удаление блока разделяемой памяти
  • shmop_open - создать или открыть блок разделяемой памяти
  • shmop_read - чтение данных из разделяемой памяти
  • shmop_size - получить размер блока разделяемой памяти
  • shmop_write - запись данных в блок разделяемой памяти

Основное использование

// 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 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);

Ответ 3

Одним из способов обмена памятью между PHP-процессами является установка кеша PHP-байт-кода, например APC. APC в основном используется для хранения байт-кода в сегменте разделяемой памяти с управлением ОС, но у него также есть API для совместного использования всего, что угодно между процессами (например, локальная версия memcache).

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

Тогда в другом месте:

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

Большая проблема с памятью обмена заключается в том, что для двух процессов шагать друг на друга становится очень легко. Таким образом, общая память лучше всего подходит для вещей, которые не меняются слишком сильно, как большие глобальные массивы.

Ответ 4

PHP имеет магические методы:

  • __get($property) Давайте реализуем доступ свойства $к объекту
  • __set($property, $value) реализуем назначение свойства $для объекта

PHP может сериализовать переменные:

  • serialize($variable) возвращает строковое представление переменной
  • unserialize($string) возвращает обратно переменную из строки

PHP может обрабатывать файлы с управлением с одновременным доступом:

  • fopen($file, 'c+') открывает файл с включенными опциями консультативной блокировки (позволяет использовать стая)
  • flock($descriptor, LOCK_SH) принимает общую блокировку (для чтения)
  • flock($descriptor, LOCK_EX) берет эксклюзивную блокировку (для написания)

Таким образом, самый простой способ совместного использования объекта между приложениями - создать класс, который реализует и использует все эти материалы для сохранения и мгновенного восстановления всех своих данных в файл.

Простая реализация этого класса может быть:

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

}

Теперь вы можете использовать этот класс, например stdClass, но с контуром файла при конструировании.

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

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

Этот пример, конечно, очень прост, он заботится о параллельном доступе к файлу, но не к переменной, в лучшей реализации вы будете использовать блокировку, подобную мьютексу.

Я просто нажал этот класс (после его завершения) на github, вы можете найти его здесь.

Ответ 5

Edit:
Вероятно, вы используете неправильную почтовую память.
Сама ваша общая память является таким массивом. Таким образом, вы должны хранить отдельные многоязычные строки непосредственно в разделяемой памяти, а не большой массив с ними.
а затем только вытаскивать строки, требуемые на конкретной странице.
все это.

В общем, для обработки некоторых данных программа должна "дублировать" ее, сохраняя ее в переменной.
Что переменные для - хранить (или "дублировать" ) некоторые внешние данные.
Например, если у вас есть какая-либо информация о пользователе в вашей базе данных, чтобы отобразить имя пользователя на веб-странице, вам нужно "дублировать" эти данные, сначала сохраняя ее в переменной PHP.
И так далее.

Вы первый, кто думает, что такой подход нужно изменить.