Автор оригинала: David Wong.
В параллельных сценариях, таких как второе убийство и захват, может быть перепроданность. На языке PHP нет собственного параллельного решения, поэтому для достижения параллельного управления необходимо использовать другие способы.
Ниже перечислены общие решения:
- При использовании очередей для обработки очереди добавляется дополнительный процесс, и в очередь помещаются одновременные запросы. Проблема параллелизма не возникает, если дополнительный процесс обрабатывается последовательно. Однако этот метод не обсуждается в данной статье из-за дополнительной поддержки процесса и серьезной задержки обработки.
- Используя характеристики транзакций базы данных для обновления атомов, этот метод должен зависеть от характеристик транзакций базы данных.
- С помощью эксклюзивной блокировки файлов при обработке запроса на заказ файл блокируется с помощью flock, и заказ может быть обработан только в том случае, если блокировка успешно получена.
I. Использование Характеристик транзакций Redis
Транзакции Redis – это атомарные операции, которые гарантируют, что данные не будут изменены другими параллельными процессами во время обработки заказа.
Пример кода:
Использование теста AB
$ ab -t 20 -c 10 http://192.168.1.104:9509/
2. Использование Эксклюзивных Блокировок Файлов (Режим Блокировки)
В режиме блокировки, если другие процессы занимают блокировку, в то время как процесс получает блокировку с исключительным доступом к файлам, процесс зависнет и будет ждать, пока другие процессы снимут блокировку, и получит блокировку самостоятельно, а затем будет выполняться дальше.
Пример кода:
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+");
// Blocking (waiting) mode, to obtain exclusive locking (written program)
If (flock ($fp, LOCK_EX)// Lock the current pointer
{
// Once the lock is successful, be assured that the order will be processed.
$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');
}
// Release lock after order processing is completed
flock($fp,LOCK_UN);
}
fclose($fp);
});
$http->start();Использование теста AB
$ ab -t 20 -c 10 http://192.168.1.104:9510/
3. Использование эксклюзивных блокировок файлов (неблокирующий режим)
В неблокирующем режиме, если другие процессы занимают блокировку, в то время как процесс получает монопольную блокировку файла, процесс немедленно определит, что блокировка получения не удалась, и продолжит выполнение.
Пример кода:
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+");
// In non-blocking mode, add LOCK_NB to lock if you don't want flock () to block at lock time
If (flock ($fp, LOCK_EX | LOCK_NB)// Lock the current pointer
{
// Once the lock is successful, be assured that the order will be processed.
$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');
}
// Release lock after order processing is completed
flock($fp,LOCK_UN);
} else {
// If the acquisition lock fails, enter here immediately to execute it.
Echo "{$uniqid} - The system is busy, please try again later." PHP_EOL;
}
fclose($fp);
});
$http->start();Использование теста AB
$ ab -t 20 -c 10 http://192.168.1.104:9511/
Наконец, сравниваются результаты испытаний трех методов обработки.
Режим транзакции Redis:
...... 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 ......
Эксклюзивная блокировка файлов (режим блокировки):
...... 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: 2.438 [ms] (mean, across all concurrent requests) Transfer rate: 58.89 [Kbytes/sec] received ......
Эксклюзивные блокировки файлов (неблокирующий режим):
...... 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: 2.321 [ms] (mean, across all concurrent requests) Transfer rate: 61.85 [Kbytes/sec] received ......
Сравнивая результаты теста, можно сделать вывод, что режим транзакции redis лучше, чем режим блокировки с исключительным доступом к файлам, а неблокирующий режим лучше, чем режим блокировки в режиме блокировки с исключительным доступом к файлам.
Вышесказанное составляет все содержание этой статьи. Я надеюсь, что это будет полезно для всех, и я надеюсь, что вы будете больше поддерживать разработчика.
Оригинал: “https://developpaper.com/several-solutions-for-php-concurrent-scenario/”