PHP 프로 세 스 간 통신 을 위 한 외부 미디어 병행 처리

프로 세 스 간 통신
프로 세 스 간 통신 은 최소 두 개의 프로 세 스 나 스 레 드 간 에 데이터 나 신 호 를 전송 하 는 기술 이나 방법 을 말한다.프로 세 스 는 컴퓨터 시스템 이 자원 을 분배 하 는 가장 작은 단위 이다.모든 프로 세 스 는 자신의 일부 독립 된 시스템 자원 을 가지 고 있 으 며 서로 격 리 되 어 있다.서로 다른 프로 세 스 가 서로 자원 에 접근 하고 조율 할 수 있 도록 프로 세 스 간 통신 이 이 루어 졌 다.
정의 에 따 르 면 프로 세 스 간 통신 을 하려 면 두 가지 문 제 를 해결 해 야 합 니 다.
  • 상호 접근:메시지 전송 과 일시 저장 매체 선택 문제;
  • 조율 작업:메시지 의 액세스 충돌 문제;
  • 글 소개 의 중심 은 바로 이런 두 가 지 를 중심 으로 하 는 것 이다.글 을 더욱 간단명료 하 게 하기 위해 여 기 는 이전에 회사 에서 한 수 요 를 예 로 들 자.
    순환 ID 생 성기 가 필요 합 니 다.Min 에서 Max 까지 의 디지털 ID 를 순환 적 으로 생 성하 고 ID 가 Max 로 증가 한 후에 Min 으로 돌아 가 다시 증가 합 니 다.여러 프로 세 스 가 동시에 요청 할 때 생 성 되 는 ID 가 다 를 수 있어 야 합 니 다.
    이 수요 가 해결 해 야 할 문 제 는 바로 우리 가 해결 해 야 할 프로 세 스 간 통신 에 해결 해 야 할 두 가지 문제 이다.
  • 은 현재 의 부가 가 치 를 전송 하고 저장 하기 위해 메시지 전송 채널 이 필요 하 다.이것 은 비교적 쉽게 해결 할 수 있 습 니 다.우리 가 자주 사용 하 는 파일,데이터 베이스,session,캐 시 등 을 모두 할 수 있 습 니 다.
  • 은 여러 프로 세 스 가 동시에 생 성기 에 접근 하여 같은 ID 를 만 드 는 문 제 를 해결 해 야 합 니 다.이 수 요 를 만족 시 키 려 면 반드시 자 물 쇠 를 사용 해 야 합 니 다.또한 여러 프로 세 스 가 읽 은 데이터 가 다 르 기 위해 서 는 서로 자 물 쇠 를 배척 해 야 합 니 다.또한 호출 성 공률 을 확보 하기 위해 서 는 자 물 쇠 를 얻 는 것 이 가장 좋 습 니 다.
  • 본 고 는 이 수요 의 서로 다른 실현 을 통 해 외부 미디어 를 통 해 진행 되 는 프로 세 스 간 통신 방식 을 소개 한다.또 PHP 언어 뿐만 아니 라 다른 언어 도 이런 방법 을 사용 할 수 있다.
    문건
    flock
    파일 은 가장 기본 적 인 저장 매체 로 메시지 전송 채널 로 사용 할 수 있 습 니 다.파일 의 액세스 와 각종 언어 는 각자 의 여러 가지 방안 이 있 습 니 다.문 제 는 다 중 프로 세 스 가 동시에 발생 할 때의 충돌 문제 입 니 다.
    액세스 충돌 문 제 를 해결 하려 면 PHP 의 flock()함 수 를 사용 합 니 다.
    bool flock ( resource $handle , int $operation [, int &$wouldblock ] )
    $handler 는 fopen($pathto_file)가 져 온 파일 핸들;
    $operation 은 파일 에 자 물 쇠 를 추가 하 는 방식 입 니 다.다음 값 을 선택 할 수 있 습 니 다.
    LOCK_SH(공유 자물쇠 획득)/LOCKEX(상호 배척 자물쇠 획득)/LOCKUN(잠 금 해제)
    여기 서 우 리 는 서로 배척 하 는 자 물 쇠 를 선택 합 니 다.한 프로 세 스 가 서로 배척 하 는 자 물 쇠 를 가 져 온 후에 다른 프로 세 스 가 자 물 쇠 를 가 져 오 려 고 시도 하면 잠 금 이 풀 릴 때 까지 막 힙 니 다.즉,자전 을 실현 합 니 다.
    이 밖 에 또 하나의 인자 LOCK 가 있 습 니 다.NB,flock 은 잠 금 을 가 져 오지 못 할 때 잠 금 이 다른 프로 세 스에 의 해 풀 릴 때 까지 기본적으로 막 혀 LOCK 로 전 달 됩 니 다.NB 와 LOCKSH 또는 LOCKEX 진행 또는 연산 결과(LOCKEX | LOCK_NB)플 로 크 는 잠 금 이 다른 프로 세 스에 의 해 차지 할 때 가 있 습 니 다.막 히 지 않 고 false 로 돌아 갑 니 다.여기 서 소개 만 할 뿐 사용 하지 않 습 니 다.
    $wouldblock 인 자 는 인용 값 입 니 다.자 물 쇠 를 가 져 오지 못 하고 모드 를 막 지 않 을 때$wouldblock 은 true 로 설 정 됩 니 다.(매 뉴 얼 에 막 혔 을 때 트 루 로 설정 된다 고 합 니 다.사실 나 도 이 변수 이름 이 이상 하 다.bug 인지 아 닌 지 모 르 겠 습 니 다.제 PHP 버 전 은 5.4.5 입 니 다.아 는 번 거 로 움 이 있 으 면 풀 어 주세요)
    코드 구현
    다음은 순환 ID 생 성기 코드 입 니 다.설명 은 다음 과 같 습 니 다.
    
    function getCycleIdFromFile($max, $min = 0) {
        $handler = fopen('/tmp/cycle_id_generator.txt', 'c+');
        if (!flock($handler, LOCK_EX)) {
            throw new Exception('error_get_file_lock!');
        }
        
        $cycle_id = trim(fread($handler, 9));
        $cycle_id++;
    
        if ($cycle_id > $max) {
            $cycle_id = $min;
        }
    
        //           ,         cycle_id
        rewind($handler);
        fwrite($handler, $cycle_id);
    
        //                   ,              
        fwrite($handler, str_repeat(' ', 9));
    
        flock($handler, LOCK_UN);
    
        return $cycle_id;
    }
    mysql
    select for update
    우리 가 자주 사용 하 는 my sql 도 중간 미디어 로 프로 세 스 간 의 통신 을 실현 할 수 있 습 니 다.우 리 는 특정한 데이터 시트 안의 한 줄 의 데 이 터 를 메시지 교환 의 중계 역 으로 규정 하고 my sql 자체 잠 금 으로 여러 프로 세 스 의 액세스 충돌 을 조정 하도록 합 니 다.
    트 랜 잭 션 의 디자인 목적 은 여러 프로 세 스 가 동시에 조회 할 때 데이터 충돌 문 제 를 해결 하기 위 한 것 입 니 다.그러나 우리 가 자주 사용 하 는 사 무 는 데이터 충돌 시 스크롤 백 되 고 데이터 에 오류 가 발생 하지 않 으 며 요청 의 병행 화 를 실현 할 수 없습니다.데이터 충돌 스크롤 백 요청 에 대해 서 는 외부 에 논리 적 재 시도 가 필요 합 니 다.
    my sql 의 문법 을 소개 합 니 다.select for update 는 고정 데이터 에 상호 배척 자 물 쇠 를 추가 하고 다른 요청 은 자 물 쇠 를 가 져 오 는 데 실 패 했 을 때 자 물 쇠 를 가 져 오 는 데 성공 할 때 까지 차단 합 니 다.my sql 은 자전 을 실현 합 니 다.
    용법 은 다음 과 같다.
    1.my sql 의 자동 제출 을 닫 고 기본 열 림 을 자동 으로 제출 합 니 다.transition 문 구 를 사용 하여 열 린 사 무 를 표시 하지 않 는 한 모든 sql 을 하나의 업무 로 직접 제출 합 니 다.여 기 는 닫 습 니 다.set autocommit=0;
    2.select for update 문 구 를 사용 하여 데이터 에 상호 배척 자 물 쇠 를 추가 합 니 다.메모:my sql 의 innodb 엔진 지원 이 필요 합 니 다.
    3.데이터 업데이트 와 처리 작업 을 진행한다.
    4.자발적으로 업 무 를 제출 하고 자동 으로 복구 제출;commit; set autocommit=1;
    코드 구현
    그리고 코드 구현:
    
    //            ,demo         。
    function getCycleIdFromMysql($max, $min = 0){
        Db::db()->execute('set autocommit = 0');
        $res = Db::db()->qsqlone('SELECT cycle_id FROM cycle_id_generator WHERE id = 1 FOR UPDATE');
    
        $cycle_id = $res['cycle_id'] + 1;
        if($cycle_id > $max){
            $cycle_id = $min;
        }
    
        Db::db()->execute("UPDATE cycle_id_generator SET cycle_id = {$cycle_id} WHERE id = 1");
    
        Db::db()->execute('commit');
        Db::db()->execute('set autocommit = 1');
    
        return $cycle_id;
    }
    redis
    incr
    redis 는 우리 가 자주 사용 하 는 캐 시 서버 로 메모리 로 데 이 터 를 저장 하기 때문에 성능 이 매우 높다.우 리 는 메시지 중계 소 로 고정된 일반 키 를 사용 한 후,incr 명령 의 원자 성과 그 실행 결과(증가 후의 값)를 이용 하여 cycle 을 실현 합 니 다.id 의 증가.
    incr(key)키 가 존재 하지 않 으 면 redis 는 먼저 값 을 0 으로 설정 한 다음 에 증가 작업 을 수행 합 니 다.
    증가 하 는 데 문제 가 없 지만 우 리 는 그 값 이 max 에 이 르 렀 을 때 min 으로 설정 하 는 것 이 필요 합 니 다.이때 프로 세 스 A 가 min 으로 업데이트 되 었 을 때 다른 프로 세 스 B 도 max 보다 큰 값 을 감지 한 다음 에 값 을 min 으로 설정 합 니 다.그러나 이때 의 값 은 max 가 아 닙 니 다.즉,값 이 중복 업데이트 되 었 을 때 돌아 오 는 값 은 반드시 중복 되 어야 합 니 다.
    이때 우 리 는 스스로 자 물 쇠 를 실현 해 야 한다.
    SETNX
    redis 의 SETNX 명령 은 키 가 존재 하 는 지 확인 하고 존재 하지 않 으 면 키 의 값 을 value 로 설정 하고 결과 1 을 되 돌려 줍 니 다.키 가 존재 하면 설정 이 실 패 했 습 니 다.값 0 을 되 돌려 줍 니 다.
    SETNX key value
    이것 이 잠 금 을 실현 할 수 있 는 것 은 키 가 한 업무 에 존재 하 는 지 확인 하고 키 값 을 설정 하 는 원자 명령 이기 때 문 입 니 다.동시에 두 프로 세 스 가 키 가 존재 하지 않 는 지 확인 한 다음 에 키 를 설정 하 는 상황 이 발생 하지 않 습 니 다.
    우 리 는 다른 값 의 존재 여 부 를 cycle 로 표시 합 니 다.id 가 다른 프로 세 스 에 의 해 수정 되 고 있 는 지 여부 입 니 다.
    코드 구현
    
     function getCycleIdFromRedis($max, $min = 0) {
        $redis = new Redis();
        $redis->connect('127.0.0.1', 6379);
        $key_id = 'cycle_id_generator';
    
        $cycle_id = $redis->incr($key_id);
        
        if ($cycle_id > $max) {
            //   "  "    =       
            $key_lock = 'cycle_id_lock';
            if (!$redis->setnx($key_lock, 1)) {
                return null;
            }
    
            $cycle_id = $min;
            $redis->set($key_id, $cycle_id);
    
            //           
            $redis->delete($key_lock);
        }
    
        $redis->close();
    
        return $cycle_id;
    }
    주의:redis 에 서 는 자 회전 잠 금 명령 이 실현 되 지 않 았 기 때문에 가장 높 은 성 공률 이 필요 하 다 면 cycle 을 감지 하고 있 습 니 다.id 가 최대 치 이 며 잠 금 가 져 오 는 데 실 패 했 을 때 재 시도 에서 종료 하고 외부 에서 재 시도 합 니 다.
    
    function getCycleId($max, $min = 0) {
        $cycle_id = getCycleIdFromRedis($max, $min);
        if (!is_null($cycle_id)) {
            return $cycle_id;
        }
        //             
        usleep(500);
        //       ,            ,cycle_id        .
        return getCycleId($max, $min);
    }
    최적화 하 다.
    심사 코드 를 보면 max-min 의 값 이 매우 작 으 면 redis 는 key 의 값 을 자주 리 셋 해 야 하고 자 물 쇠 를 자주 추가 해 야 하 며 다시 시도 하 는 것 도 많다 는 것 을 알 수 있 습 니 다.여기 서 나 는 최적화 방법 을 제공한다.
    우 리 는 max 를 매우 큰 값 으로 설정 합 니 다.(max-min 으로 제거 할 수 있 으 려 면)값 을 되 돌 릴 때 잠시 처리 하고$current%($max-$min)+$min 을 되 돌려 줍 니 다.이렇게 하면 키 는 큰 값 으로 점차적으로 증가 해 야 리 셋 되 고 잠 금 논리 와 외층 논 리 는 거의 실행 되 지 않 아 효율 을 높이 는 목적 을 달성 할 수 있다.
    총결산
    여기 서 위 에서 말 한 세 가지 방법 을 간단하게 평가 해 보 자.
    성능 상 테스트 가 없 으 며,redis 의 성능 은 ID 의 크기 차이 와 관련 이 있 지만,ID 의 크기 차이 가 큰 경우 redis 가 더 좋 을 것 으로 예상 된다.
    코드 에 있어 서 매우 직관 적 이 고 my sql 을 사용 하 는 것 이 매우 간결 하 며 redis 는 스스로 자전 을 실현 해 야 하기 때문에 비교적 징그럽다.
    실현 에 있어 서 당연히 파일 이 가장 편리 하고 추가 되 지 않 습 니 다.
    이상 은 PHP 프로 세 스 간 통신 을 병행 처리 하 는 외부 미디어 에 대한 상세 한 내용 입 니 다.PHP 프로 세 스 간 통신 을 병행 처리 하 는 외부 미디어 에 대한 자 료 는 다른 관련 글 을 주목 하 십시오!

    좋은 웹페이지 즐겨찾기