Обмен переменными/памятью между всеми процессами PHP
Можно ли обмениваться переменными и массивами между всеми процессами PHP без дублирования их?
Используя memcached, я думаю, что PHP дублирует используемую память:
$array = $memcache->get('array');
$ array будет содержать копию из memcached.
Итак, моя идея: может существовать переменная static, которая уже была определена и разделена между всеми процессами.
Ответы
Ответ 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.
И так далее.
Вы первый, кто думает, что такой подход нужно изменить.