2011-04-09 2 views
17

을 복제하지 않고 모든 PHP 프로세스 간에 변수 및 배열을 공유 할 수 있습니까?모든 PHP 프로세스간에 변수/메모리 공유

memcached를 사용하여, 나는 PHP가 사용하는 메모리를 복제 생각 :
$array = $memcache->get('array');
$ 배열되는 memcached에서 사본을 포함합니다.

제 생각에는 정적 변수가 이미 정의되어 있고 모든 프로세스간에 공유되어있을 수 있습니다.

+1

이 배열이 큰 것입니다 - 공유 메모리 블럭의 크기

  • shmop_write을 얻기? –

  • +0

    예. 컨텍스트를 조금 더 추가 할 수 있습니까? 데이터를 데이터베이스에 저장하고 현재 스크립트에서 필요한 비트만 검색하는 방법은 무엇입니까? –

    +0

    이것은 대개 데이터베이스에 데이터를 저장하고 필요한 것을 가져 오는 것으로 해결됩니다. –

    답변

    4

    기본적으로 불가능합니다. 모든 솔루션은 항상 현재 범위에 내용을 복사합니다. 그렇지 않으면 액세스하지 못하게됩니다.

    정확하게 알고 싶지 않지만, 예를 들어 gearman 작업과 같이 "외부"작업을 수행 한 다음 전체 배열 대신 프로세스의 결과를 캐치 할 수 있습니다.

    또한 "큰"배열을 조각으로 분할 한 다음 항상 apc 또는 memcached에서 현재 필요한 부분을 검색 할 수 있습니다.

    +5

    좋아요, 마지막으로 유용한 답변 : "불가능". 나는 모욕이나 풍자보다는 오히려 성실합니다. 고마워, 이건 내 받아 들여진 대답이다. – Nuno

    +0

    3 단락에 대해서는 이미 다른 방법으로이 방법을 사용합니다. 내 걱정은 내가 내 질문에서 말했듯이 내가 무엇이 다가오고 있는지 정말로 알지 못할 때이다. – Nuno

    +2

    @Nuno 그처럼 민감하지 마십시오. 아무도 당신을 모욕하지 않았습니다. 대답이 도움이되지 않았다면 상처를 입히지 말고 질문을 개선하십시오. –

    0

    편집 :
    아마도 공유 메모리를 잘못 사용하고있을 수 있습니다.
    공유 메모리 자체가 배열입니다. 그래서 별도의 다국어 문자열을 공유 메모리에 직접 저장해야하며 큰 배열은 저장하지 않아야합니다.
    다음 특정 페이지에 필요한 문자열 만 당깁니다.
    그게 전부입니다.

    일반적으로 일부 데이터를 처리하려면 프로그램에 변수를 저장하여 "복제"해야합니다.
    그게 변수입니다. - 외부 데이터를 저장 (또는 "복제")하는 것입니다.
    예를 들어 데이터베이스에 사용자 정보가있는 경우 웹 페이지에 사용자 이름을 표시하려면이 데이터를 "복제"하여 PHP 변수에 먼저 저장해야합니다.
    등등.

    이러한 접근 방식을 변경해야한다고 생각하는 사람이 누구입니까?

    7

    PHP 프로세스간에 메모리를 공유하는 한 가지 방법은 APC과 같은 PHP 바이트 코드 캐시를 설치하는 것입니다. APC는 주로 바이트 코드를 OS 관리 공유 메모리 세그먼트에 저장하는 데 사용되지만 프로세스간에 원하는 내용 (예 : memcache의 로컬 버전)을 공유하기위한 API도 제공합니다. 그런 다음 다른 곳

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

    : 공유 메모리와

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

    큰 문제는 두 프로세스가 서로의 발을 단계로 매우 쉽게 될 것입니다. 따라서 공유 메모리는 큰 글로벌 배열처럼 너무 많이 변경되지 않는 것들에 가장 좋습니다.

    +0

    참조 Memcached와 동일하게 보입니다. 어쨌든 대답 해 주셔서 감사합니다. – Nuno

    +1

    @NunoPeralta, Shmop은 어떨까요? 아래를 참조하십시오. – Pacerier

    +0

    이것은 잘못되었습니다. apc_store 등은 프로세스간에 메모리를 공유 할 수 없습니다. 각 프로세스는 자체 메모리 세그먼트를 할당합니다. 즉, php-fpm과 php-cli간에 메모리를 공유 할 수 없습니다 (다른 php-fpm 요청을 공유하는 동안 작동합니다). – bhelm

    3

    PHP는 매직 메소드가 있습니다

    • __get($property)
    • __set($property, $value) 우리가 물체에 $ 속성의 대입을 구현할 수 있도록 우리가 물체에 $ 속성의 액세스를 구현할 수 있도록

    PHP는 변수를 직렬화 할 수 있습니다 :

    • (10 개) 반환 변수
    • 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에서이 클래스를 푸시했습니다 (here). Shmop를 사용

    +3

    질문에 대한 오해가 있습니다. – Pacerier

    +0

    좋아요. 파일을 사용하는 것이 서버의 메모리를 사용하지 않으므로 가장 간단한 방법 일 수 있습니다. 데이터베이스를 묻는 것보다 빠르다고 생각합니다. – Meloman

    +0

    이것은 데이터베이스를 사용하는 것과 다르지 않습니다. 아이디어는 디스크가 아닌 메모리에서 변수를 공유하는 것입니다. –

    18

    :

    은 shmop는 PHP는 유닉스 공유 메모리 세그먼트를 읽고 쓰기, 생성 및 삭제할 수 있습니다이 기능의 설정 사용하기 쉽습니다.

    은에서 : http://www.php.net/manual/en/intro.shmop.php

    외부 라이브러리는이 확장을 만들 필요하지 않습니다.

    공유 메모리 기능

    • shmop_close - 닫기
    • 공유 메모리 블럭
    • shmop_delete - 삭제 공유 메모리 블럭
    • shmop_open - 만들거나 열 공유 메모리 블럭
    • shmop_read - 공유 메모리 블록에서 데이터 읽기
    • shmop_size - 공유 메모리 블럭에 데이터를 쓰기

    기본 사용법

    // 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); 
    
    +1

    http://stackoverflow.com/a/8631902/632951 – Pacerier

    +1

    [shmop을 사용하려면 설정 라인에서 ** - enable-shmop ** 매개 변수로 PHP를 컴파일해야합니다.] (http : // php.net/manual/en/shmop.installation.php) – Pang

    관련 문제