PHP 프로 세 스 간 통신 을 위 한 외부 미디어 병행 처리
7852 단어 php프로 세 스커 뮤 니 케 이 션외부 매체
프로 세 스 간 통신 은 최소 두 개의 프로 세 스 나 스 레 드 간 에 데이터 나 신 호 를 전송 하 는 기술 이나 방법 을 말한다.프로 세 스 는 컴퓨터 시스템 이 자원 을 분배 하 는 가장 작은 단위 이다.모든 프로 세 스 는 자신의 일부 독립 된 시스템 자원 을 가지 고 있 으 며 서로 격 리 되 어 있다.서로 다른 프로 세 스 가 서로 자원 에 접근 하고 조율 할 수 있 도록 프로 세 스 간 통신 이 이 루어 졌 다.
정의 에 따 르 면 프로 세 스 간 통신 을 하려 면 두 가지 문 제 를 해결 해 야 합 니 다.
순환 ID 생 성기 가 필요 합 니 다.Min 에서 Max 까지 의 디지털 ID 를 순환 적 으로 생 성하 고 ID 가 Max 로 증가 한 후에 Min 으로 돌아 가 다시 증가 합 니 다.여러 프로 세 스 가 동시에 요청 할 때 생 성 되 는 ID 가 다 를 수 있어 야 합 니 다.
이 수요 가 해결 해 야 할 문 제 는 바로 우리 가 해결 해 야 할 프로 세 스 간 통신 에 해결 해 야 할 두 가지 문제 이다.
문건
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;
}
mysqlselect 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;
}
redisincr
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 프로 세 스 간 통신 을 병행 처리 하 는 외부 미디어 에 대한 자 료 는 다른 관련 글 을 주목 하 십시오!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Laravel - 변환된 유효성 검사 규칙으로 API 요청 제공동적 콘텐츠를 위해 API를 통해 Laravel CMS에 연결하는 모바일 앱(또는 웹사이트) 구축을 고려하십시오. 이제 앱은 CMS에서 번역된 콘텐츠를 받을 것으로 예상되는 다국어 앱이 될 수 있습니다. 일반적으로 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.