在所有 PHP 进程之间共享变量/内存
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5605656/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Share variables/memory between all PHP processes
提问by Nuno
Is it possible to share variables and arrays between all PHP processes without duplicating them?
是否可以在所有 PHP 进程之间共享变量和数组而不复制它们?
Using memcached, I think PHP duplicates the used memory:$array = $memcache->get('array');
$array will contain a copy from memcached.
使用 memcached,我认为 PHP 会复制使用的内存:$array = $memcache->get('array');
$array 将包含来自 memcached 的副本。
So my idea is, there could be a staticvariable that was already defined, and shared between all processes.
所以我的想法是,可能已经定义了一个静态变量,并在所有进程之间共享。
采纳答案by KingCrunch
By default its simply not possible. Every solution will always copy the content into the current scope, because if not, there is no way to access it.
默认情况下,它根本不可能。每个解决方案都会将内容复制到当前范围内,因为如果没有,则无法访问它。
I dont know, what exactly want to do, but maybe you can do that "outside", for example as a gearmanjob, and then just catch the results of the process, instead of the whole array.
我不知道,到底想做什么,但也许你可以在“外面”做那个,例如作为一个齿轮工作,然后只是捕捉过程的结果,而不是整个数组。
You can also think about splitting the "big" array into slices and then always retrieve the part you currently need from an apc or memcached.
您还可以考虑将“大”数组拆分为多个切片,然后始终从 apc 或 memcached 中检索您当前需要的部分。
回答by RafaSashi
Using Shmop
:
使用Shmop
:
Shmop is an easy to use set of functions that allows PHP to read, write, create and delete Unix shared memory segments.
Shmop 是一组易于使用的函数,它允许 PHP 读取、写入、创建和删除 Unix 共享内存段。
from: http://www.php.net/manual/en/intro.shmop.php
来自:http: //www.php.net/manual/en/intro.shmop.php
No external libraries are needed to build this extension.
构建此扩展不需要外部库。
The shared Memory Functions
共享内存函数
- shmop_close — Close
- shared memory block
- shmop_delete — Delete shared memory block
- shmop_open — Create or open shared memory block
- shmop_read — Read data from shared memory block
- shmop_size — Get size of shared memory block
- shmop_write — Write data into shared memory block
- shmop_close — 关闭
- 共享内存块
- shmop_delete — 删除共享内存块
- shmop_open — 创建或打开共享内存块
- shmop_read — 从共享内存块读取数据
- shmop_size — 获取共享内存块的大小
- shmop_write — 将数据写入共享内存块
Basic usage
基本用法
// 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);
回答by wm_eddie
One way to share memory between PHP processes is to install a PHP-bytecode cache like APC. APC is primarily used for storing the bytecode into an OS managed shared-memory segment, but it also has an API for sharing anything you want between processes (like a local version of memcache).
在 PHP 进程之间共享内存的一种方法是安装像APC这样的 PHP 字节码缓存。APC 主要用于将字节码存储到操作系统管理的共享内存段中,但它也有一个 API 用于在进程之间共享您想要的任何内容(如本地版本的内存缓存)。
<?php
$foobar = array('foo', 'bar');
apc_store('foobar', $foobar);
?>
Then elsewhere:
然后在别处:
<?php
$foobar = apc_fetch('foobar');
var_dump($foobar);
?>
The big problem with sharing-memory is that it becomes very easy for two processes to step on each other's foot. So shared memory is best for things that don't change too much, like big global arrays.
共享内存的一个大问题是两个进程很容易互相踩踏。所以共享内存最适合不会改变太多的东西,比如大的全局数组。
回答by Alain Tiemblo
PHP has magic methods:
PHP 有神奇的方法:
__get($property)
let us implement the access of a $property on an object__set($property, $value)
let us implement the assignation of a $property on an object
__get($property)
让我们在对象上实现 $property 的访问__set($property, $value)
让我们在对象上实现 $property 的分配
PHP can serialize variables:
PHP 可以序列化变量:
serialize($variable)
returns a string representation of the variableunserialize($string)
returns back a variable from a string
serialize($variable)
返回变量的字符串表示unserialize($string)
从字符串返回一个变量
PHP can handle files, with concurrent-access management:
PHP 可以处理文件,具有并发访问管理:
fopen($file, 'c+')
opens a file with advisory lock options enabled (allow you to use flock)flock($descriptor, LOCK_SH)
takes a shared lock (for reading)flock($descriptor, LOCK_EX)
takes an exclusive lock (for writting)
fopen($file, 'c+')
打开一个启用了咨询锁定选项的文件(允许您使用 flock)flock($descriptor, LOCK_SH)
需要一个共享锁(用于读取)flock($descriptor, LOCK_EX)
需要一个排他锁(用于写入)
So, the easiest way to share an object between apps is to create a class that implements and use all those stuffs to save and restore instantly all its data into a file.
因此,在应用程序之间共享对象的最简单方法是创建一个类,该类实现并使用所有这些东西将其所有数据立即保存并恢复到文件中。
A simple implementation of that class could be :
该类的一个简单实现可能是:
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;
}
}
Now, you can use this class like stdClass
, but with a file path when constructing.
现在,您可以像 一样使用此类stdClass
,但在构造时使用文件路径。
$obj = new Synchro("/tmp/test.sync");
$obj->hello = 'world';
// ... and in another process...
echo $obj->hello;
This example is of course very simple, it takes care about concurrent access to a file but not to a variable, in a better implementation you'll use a mutex-like lock.
这个例子当然非常简单,它关注的是对文件的并发访问,而不是对变量的并发访问,在更好的实现中,您将使用类似互斥锁的锁。
I just pushed this class (after completing it) on github, you can find it here.
我刚刚在github上推送了这个类(完成后),你可以在这里找到它。
回答by Your Common Sense
Edit:
You are probably using shared memory wrong way.
Your shared memory itself being such array. So you have to store separate multilanguage stringsdirectly in shared memory, not big array with them.
and then only pull strings, required on particular page.
that's all.
编辑:
您可能以错误的方式使用共享内存。
您的共享内存本身就是这样的数组。因此,您必须将单独的多语言字符串直接存储在共享内存中,而不是包含它们的大数组。
然后只拉线,在特定页面上需要。
就这样。
In general, to process some data, a program have to "duplicate" it, by storing it in a variable.
That's what variables are for - to store (or "duplicate") some outside data.
For example, if you have some user info in your database, to display a username on a web page you have to "duplicate" this data, storing it in PHP variable first.
And so on.
通常,要处理某些数据,程序必须通过将其存储在变量中来“复制”它。
这就是变量的用途 - 存储(或“复制”)一些外部数据。
例如,如果您的数据库中有一些用户信息,要在网页上显示用户名,您必须“复制”这些数据,首先将其存储在 PHP 变量中。
等等。
You are first who thinks that such approach needs to be changed.
您是第一个认为这种方法需要改变的人。