在所有 PHP 进程之间共享变量/内存

发布于 2024-10-31 02:15:17 字数 237 浏览 3 评论 0原文

是否可以在所有 PHP 进程之间共享变量和数组而不重复

使用 memcached,我认为 PHP 会重复使用的内存:
$array = $memcache->get('array');
$array 将包含来自 memcached 的副本。

所以我的想法是,可能有一个已经定义的静态变量,并在所有进程之间共享。

Is it possible to share variables and arrays between all PHP processes without duplicating them?

Using memcached, I think PHP duplicates the used memory:
$array = $memcache->get('array');
$array will contain a copy from memcached.

So my idea is, there could be a static variable that was already defined, and shared between all processes.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

相权↑美人 2024-11-07 02:15:17

使用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);

Using Shmop:

Shmop is an easy to use set of functions that allows PHP to read,
write, create and delete Unix shared memory segments.

from: 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

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);
涫野音 2024-11-07 02:15:17

在 PHP 进程之间共享内存的一种方法是安装 PHP 字节码缓存,例如 APC。 APC 主要用于将字节码存储到操作系统管理的共享内存段中,但它也有一个 API,用于在进程之间共享您想要的任何内容(例如本地版本的 memcache)。

<?php
   $foobar = array('foo', 'bar');
   apc_store('foobar', $foobar);
?>

然后是其他地方:

<?php
    $foobar = apc_fetch('foobar');
    var_dump($foobar);
?>

共享内存的一个大问题是两个进程很容易互相踩对方的脚。因此,共享内存最适合那些不会改变太多的东西,比如大型全局数组。

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
   $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.

记忆之渊 2024-11-07 02:15:17

默认情况下这是不可能的。每个解决方案总是会将内容复制到当前作用域中,因为如果没有,则无法访问它。

我不知道,到底想做什么,但也许你可以“在外面”做,例如作为 gearman作业,然后只捕获该过程的结果,而不是整个数组。

您还可以考虑将“大”数组拆分为多个切片,然后始终从 apc 或 memcached 检索当前需要的部分。

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 gearman job, 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.

酷到爆炸 2024-11-07 02:15:17

PHP 有一些神奇的方法:

  • __get($property) 让我们实现对对象 $property 的访问
  • __set($property, $value) 让我们实现对对象的赋值对象上的 $property

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 上推送了这个课程(完成后),你可以在这里找到它

PHP has magic methods:

  • __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

PHP can serialize variables:

  • serialize($variable) returns a string representation of the variable
  • unserialize($string) returns back a variable from a string

PHP can handle files, with concurrent-access management:

  • 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)

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.

$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.

木森分化 2024-11-07 02:15:17

编辑:
您可能以错误的方式使用共享内存。
你的共享内存本身就是这样的数组。因此,您必须将单独的多语言字符串直接存储在共享内存中,而不是使用大数组。
然后仅拉动特定页面所需的字符串。
就这样。

一般来说,要处理某些数据,程序必须通过将其存储在变量中来“复制”它。
这就是变量的用途 - 存储(或“复制”)一些外部数据。
例如,如果您的数据库中有一些用户信息,要在网页上显示用户名,您必须“复制”此数据,首先将其存储在 PHP 变量中。
等等。

你是第一个认为这种做法需要改变的人。

Edit:
You are probably using shared memory wrong way.
Your shared memory itself being such array. So you have to store separate multilanguage strings directly 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.

You are first who thinks that such approach needs to be changed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文