There is no native concurrency solution in PHP, so you need to use other ways to implement concurrency control. In fact, there are many different solutions, but today I just want to give you an example.

The three common solutions listed are:

Use queue, an extra process to process the queue, concurrent requests are put into the queue, by the extra process serial processing, concurrency problem does not exist, but to support the extra process and processing delay is serious, this article will not discuss this method.

Using the database transaction characteristics, do atomic update, this method needs to rely on the database transaction characteristics.

With file exclusive locking, when processing an order request, use Flock to lock a file so that the order can only be processed if the file is successfully locked.

First, use Redis transaction characteristics

Redis transactions are atomic operations that ensure that data is not modified by other concurrent processes during order processing.

Sample code:

<? PHP $HTTP = new swoole_http_server("0.0.0.0", 9509); $HTTP ->set(array(' reacTOR_num '=> 2, //reactor thread num' worker_num' => 4)); $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); $redis->watch('rest_count'); $rest_count = intval($redis->get("rest_count")); / / simulation only order 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->multi(); $redis->lPush('uniqids', $value); $redis->decr('rest_count'); $replies = $redis->exec(); // If the rest_count value is changed by another concurrent process, the above transaction will be rolled back if (! $replies) {echo "Order {$value} rollback". } } $redis->unwatch(); }); $http->start();Copy the code

Use the AB test

20 - $ab - t c 10 http://192.168.1.104:9509/Copy the code

Use file exclusive lock (blocking mode)

In blocking mode, if a process obtains the file exclusive lock while another process is occupying the lock, the process suspends until the lock is released by another process. After obtaining the lock, the process can proceed.

Sample code:

<? 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)) {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'); } // After the order is processed, release the lock flock($fp, LOCK_UN); } fclose($fp); }); $http->start();Copy the code

Use the AB test

20 - $ab - t c 10 http://192.168.1.104:9510/Copy the code

Use file exclusive lock (non-blocking mode)

In non-blocking mode, if a process acquires an exclusive file lock while another process is holding it, the process immediately determines that the lock failed and continues. \

Sample code:

<? PHP $HTTP = new swoole_http_server("0.0.0.0", 9511); $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+"); / / non-blocking mode, if do not want the flock () when the locking block, then add LOCK_NB to lock the if (flock ($fp, LOCK_EX | LOCK_NB)) / / lock the current pointer {/ / success after the lock, $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'); } // After the order is processed, release the lock flock($fp,LOCK_UN); } else {echo "{$uniqID} - the system is busy, please try again later ". } fclose($fp); }); $http->start();Copy the code

Use the AB test

20 - $ab - t c 10 http://192.168.1.104:9511/Copy the code

Finally, the test results of the three methods are compared

Redis transaction mode:

. Concurrency Level: 10 Time taken for Tests: 20.005 seconds Complete Requests: 17537 Failed requests: 0 Total transferred: 2578380 bytes HTML transferred: 0 bytes Requests per second: 876.62 [#/ SEC] (mean) Time per request: 11.407 [ms] (mean) Time per request: 1.141 [MS] (mean, across all concurrent requests) Transfer rate: 125.86 [Kbytes/ SEC] received......Copy the code

File exclusive lock (blocking mode) :

. Concurrency Level: 10 Time taken for Tests: 20.003 seconds Complete Requests: 8205 Failed requests: 0 Total transferred: 1206282 bytes HTML transferred: 0 bytes Requests per second: 410.19 [#/ SEC] (mean) Time per request: 24.379 [ms] (mean) Time per request: 24.379 2.438 [MS] (mean, across all concurrent requests) Transfer rate: 58.89 [Kbytes/ SEC] received......Copy the code

File exclusive lock (non-blocking mode) :

. Concurrency Level: 10 Time taken for Tests: 20.002 seconds Complete requests: 8616 Failed requests: 0 Total transferred: 1266846 bytes HTML transferred: 0 bytes Requests per second: 430.77 [#/ SEC] (mean Time per request: 23.214 [ms] (mean Time per request: 23.214) 2.321 [MS] (mean, across all concurrent requests) Transfer rate: 61.85 [Kbytes/ SEC] received......Copy the code

The results show that redis transaction mode is better than file exclusive lock mode, while file exclusive lock mode is better than non-blocking mode.

I hope the above content can help you. Many PHPer will encounter some problems and bottlenecks when they are advanced, and they have no sense of direction when writing too many business codes. I have sorted out some information, including but not limited to: Distributed architecture, high scalability, high performance, high concurrency, server performance tuning, TP6, Laravel, Redis, Swoft, Kafka, Mysql optimization, shell scripting, Docker, microservices, Nginx, etc. Many knowledge points can be free to share with you