Nun*_*uno 19 php shared-memory
是否可以在所有PHP进程之间共享变量和数组而不重复它们?
使用memcached,我认为PHP重复使用的内存:
$array = $memcache->get('array');
$ array将包含memcached的副本.
所以我的想法是,可能有一个已定义的静态变量,并在所有进程之间共享.
Raf*_*shi 21
使用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);
Run Code Online (Sandbox Code Playgroud)
在PHP进程之间共享内存的一种方法是安装像APC这样的PHP字节码缓存.APC主要用于将字节码存储到OS管理的共享内存段中,但它还具有用于在进程之间共享任何内容的API(如本地版本的memcache).
<?php
$foobar = array('foo', 'bar');
apc_store('foobar', $foobar);
?>
Run Code Online (Sandbox Code Playgroud)
其他地方:
<?php
$foobar = apc_fetch('foobar');
var_dump($foobar);
?>
Run Code Online (Sandbox Code Playgroud)
共享内存的一个大问题是两个进程很容易互相踩踏.因此共享内存最适合那些不会发生太大变化的事情,比如大型全局数组.
PHP具有魔术方法:
__get($property) 让我们实现对对象的$ property访问__set($property, $value) 让我们在对象上实现$ property的分配PHP可以序列化变量:
serialize($variable) 返回变量的字符串表示形式unserialize($string) 从字符串返回一个变量PHP可以通过并发访问管理来处理文件:
fopen($file, 'c+') 打开一个启用了建议锁定选项的文件(允许您使用flock)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;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,您可以像使用此类stdClass,但在构造时使用文件路径。
$obj = new Synchro("/tmp/test.sync");
$obj->hello = 'world';
// ... and in another process...
echo $obj->hello;
Run Code Online (Sandbox Code Playgroud)
这个例子当然很简单,它关心并发访问文件而不是变量,在更好的实现中,您将使用类似互斥锁的锁。
我刚刚在github上推送了该类(完成后),您可以在这里找到它。
| 归档时间: |
|
| 查看次数: |
24171 次 |
| 最近记录: |