在所有PHP进程之间共享变量/内存
是否有可能在所有PHP进程之间共享变量和数组而不复制它们?在所有PHP进程之间共享变量/内存
使用memcached的,我认为PHP重复使用的内存:$array = $memcache->get('array');
$阵列将包含从memcached的副本。
所以我的想法是,可能有一个静态变量已被定义,并在所有进程之间共享。
默认情况下它根本不可能。每个解决方案都会将内容复制到当前范围内,因为如果没有,则无法访问它。
我不知道,究竟想要做什么,但也许你可以做到“外部”,例如作为gearman工作,然后只是捕获过程的结果,而不是整个数组。
您还可以考虑将“大”数组分割成片,然后始终从apc或memcached中检索当前需要的部分。
编辑:
您可能正在使用共享内存错误的方式。
你的共享内存本身就是这样的数组。因此,您必须将独立的多语言字符串直接存储在共享内存中,而不是使用它们的大数组。
然后只拉字符串,在特定页面上需要。这就是全部。
通常,为了处理一些数据,程序必须通过将其存储在一个变量中来“复制”它。
这就是变量的用途 - 存储(或“复制”)一些外部数据。例如,如果在数据库中有一些用户信息,要在网页上显示用户名,则必须“复制”该数据,首先将其存储在PHP变量中。
依此类推。
你是第一个认为这种方法需要改变的人。
在PHP进程之间共享内存的一种方法是安装一个PHP字节码缓存,如APC。 APC主要用于将字节码存储到OS管理的共享内存段中,但它也具有用于在进程之间共享任何需要的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)
需要一个e XCLUSIVE锁(用于书面方式)
所以,共享应用程序之间的对象最简单的方法是创建一个类,它实现和使用所有这些东西给它的所有数据保存和瞬间恢复到文件中。
的简单实现类的可能是:现在
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上推了这个类(完成之后),你可以找到它here。
使用Shmop
:
Shmop是一个易于使用的设置的功能,它允许PHP读,写 ,创建和删除的Unix共享内存段。
来自: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'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);
是你的阵列大吗? – 2011-04-09 14:39:25
是的。你可以添加更多的上下文吗?如何将数据存储在数据库中,并只检索当前脚本中需要的位? – 2011-04-09 15:04:09
这通常是通过将数据存储在数据库中并仅提取所需内容来解决的。 – 2011-04-09 22:43:35