일반적인 해결 방법은 다음과 같습니다.
1. 대기열을 사용하여 대기열을 처리합니다. 동시 요청은 대기열에 배치되고 추가 프로세스에 의해 순차적으로 처리됩니다. , 그러나 추가 프로세스 지원 및 처리 지연이 심각하므로 이 문서에서는 이 방법에 대해 먼저 논의하지 않습니다.
2. 데이터베이스의 트랜잭션 특성을 사용하여 원자성 업데이트를 수행합니다. 이 방법은 데이터베이스의 트랜잭션 특성에 의존해야 합니다.
3. 파일 단독 잠금 기능을 이용하면 주문 요청 처리 시 Flock을 이용해 파일을 잠글 수 있습니다.
1. Redis 트랜잭션 기능 활용
redis 트랜잭션은 원자성 작업이므로 주문 처리 중에 다른 동시 프로세스에 의해 데이터가 수정되지 않도록 할 수 있습니다.
샘플 코드:
<?php $http = new swoole_http_server("0.0.0.0", 9509); // 监听 9509 $http->set(array( 'reactor_num' => 2, //reactor thread num 'worker_num' => 4 //worker process num )); $http->on('request', function (swoole_http_request $request, swoole_http_response $response) { $uniqid = uniqid('uid-', TRUE); // 模拟唯一用户ID $redis = new Redis(); $redis->connect('127.0.0.1', 6379); // 连接 redis $redis->watch('rest_count'); // 监测 rest_count 是否被其它的进程更改 $rest_count = intval($redis->get("rest_count")); // 模拟唯一订单ID if($rest_count > 0){ $value = "{$rest_count}-{$uniqid}"; // 表示当前订单,被当前用户抢到了 // do something ... 主要是模拟用户抢到单后可能要进行的一些密集运算 $rand = rand(100, 1000000); $sum=0; for ($i=0;$i<$rand;$i++){ $sum+=$i; } // redis 事务 $redis->multi(); $redis->lPush('uniqids', $value); $redis->decr('rest_count'); $replies = $redis->exec(); // 执行以上 redis 事务 // 如果 rest_count 的值被其它的并发进程更改了,以上事务将回滚 if(!$replies){ echo "订单 {$value} 回滚".PHP_EOL; } } $redis->unwatch(); }); $http->start();
ab test 사용
$ ab -t 20 -c 10 http://192.168.1.104:9509/
2. 파일 배타적 잠금 사용(차단 모드)
차단 모드에서 해당 프로세스가 파일 배타적 잠금을 획득 중이고 다른 프로세스가 잠금을 점유 중인 경우, this 프로세스는 정지되어 다른 프로세스가 잠금을 해제할 때까지 기다린 다음 잠금 자체를 획득한 후 실행을 계속합니다.
샘플 코드:
<?php $http = new swoole_http_server("0.0.0.0", 9510); $http->set(array( 'reactor_num' => 2, //reactor thread num 'worker_num' => 4 //worker process num )); $http->on('request', function (swoole_http_request $request, swoole_http_response $response) { $uniqid = uniqid('uid-', TRUE); $redis = new Redis(); $redis->connect('127.0.0.1', 6379); $fp = fopen("lock.txt", "w+"); // 阻塞(等待)模式, 要取得独占锁定(写入的程序) if(flock($fp,LOCK_EX)) //锁定当前指针 { // 成功取得锁后,放心处理订单 $rest_count = intval($redis->get("rest_count")); $value = "{$rest_count}-{$uniqid}"; if($rest_count > 0){ // do something ... $rand = rand(100, 1000000); $sum=0; for ($i=0;$i<$rand;$i++){ $sum+=$i; } $redis->lPush('uniqids', $value); $redis->decr('rest_count'); } // 订单处理完成后,再释放锁 flock($fp,LOCK_UN); } fclose($fp); }); $http->start();
ab 테스트 사용
$ ab -t 20 -c 10 http://192.168.1.104:9510/
추천 튜토리얼: PHP 튜토리얼
위 내용은 PHP의 일반적인 동시성 시나리오에 대한 솔루션의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!