是否有可能在所有PHP進程之間共享變量和數組而不復制它們?在所有PHP進程之間共享變量/內存
使用memcached的,我認爲PHP重複使用的內存:
$array = $memcache->get('array');
$陣列將包含從memcached的副本。
所以我的想法是,可能有一個靜態變量已被定義,並在所有進程之間共享。
是否有可能在所有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
無需外部庫需要建立這個擴展。
共享存儲器功能
基本用法
// 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