Можно ли обмениваться переменными и массивами между всеми процессами PHP без их дублирования ?
Используя memcached, я думаю, что PHP дублирует используемую память:
$array = $memcache->get('array');
$ array будет содержать копию из memcached.
Поэтому моя идея: может существовать статическая переменная, которая уже была определена и разделена между всеми процессами.
По умолчанию его просто невозможно. Каждое решение всегда будет копировать содержимое в текущую область, потому что если нет, то нет доступа к нему.
Я не знаю, что именно нужно делать, но, возможно, вы можете сделать это «снаружи», например, как задание ретранслятора , а затем просто поймать результаты процесса, а не весь массив.
Вы также можете подумать о разделении «большого» массива на срезы, а затем всегда извлекать нужную вам часть из apc или memcached.
Использование Shmop
:
Shmop – это простой в использовании набор функций, который позволяет PHP читать, записывать, создавать и удалять сегменты разделяемой памяти Unix.
от: http://www.php.net/manual/en/intro.shmop.php
Для создания этого расширения внешние библиотеки не нужны.
Общие функции памяти
Основное использование
// 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);
Одним из способов обмена памятью между PHP-процессами является установка кеша PHP-байт-кода, такого как APC . APC в основном используется для хранения байт-кода в сегменте разделяемой памяти с управлением ОС, но у него также есть API для совместного использования всего, что угодно между процессами (например, локальная версия memcache).
<?php $foobar = array('foo', 'bar'); apc_store('foobar', $foobar); ?>
Затем в другом месте:
<?php $foobar = apc_fetch('foobar'); var_dump($foobar); ?>
Большая проблема с памятью обмена заключается в том, что для процессов на ступени друг на друга становится очень легко. Таким образом, общая память лучше всего подходит для вещей, которые не меняются слишком сильно, как большие глобальные массивы.
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
, но с файловым stdClass
при конструировании.
$obj = new Synchro("/tmp/test.sync"); $obj->hello = 'world'; // ... and in another process... echo $obj->hello;
Этот пример, конечно, очень прост, он заботится о параллельном доступе к файлу, но не к переменной, в лучшей реализации вы будете использовать блокировку, подобную мьютексу.
Я просто нажал этот класс (после его завершения) на github, вы можете найти его здесь .
Редактировать:
Возможно, вы неправильно используете общую память.
Сама ваша общая память является таким массивом. Таким образом, вы должны хранить отдельные многоязычные строки непосредственно в разделяемой памяти, а не большой массив с ними.
а затем вытаскивать только строки, требуемые на конкретной странице.
это все.
В общем, для обработки некоторых данных программа должна «дублировать» ее, сохраняя ее в переменной.
Вот какие переменные предназначены для хранения (или «дублирования») некоторых внешних данных.
Например, если у вас есть какая-либо информация о пользователе в вашей базе данных, чтобы отобразить имя пользователя на веб-странице, вы должны «дублировать» эти данные, сначала сохраняя ее в переменной PHP.
И так далее.
Вы первый, кто думает, что такой подход нужно изменить.