Maison  >  Article  >  développement back-end  >  Solutions aux scénarios de concurrence courants en PHP

Solutions aux scénarios de concurrence courants en PHP

王林
王林original
2019-11-13 17:51:262375parcourir

Solutions aux scénarios de concurrence courants en PHP

Les solutions courantes sont les suivantes :

1 Utilisez une file d'attente, démarrez un processus supplémentaire pour gérer la file d'attente et placez toutes les demandes simultanées. dans la file d'attente. Si des processus supplémentaires sont traités en série, le problème de concurrence n'existera pas. Toutefois, une prise en charge de processus supplémentaire est requise et le retard de traitement est important. Cet article ne traitera pas de cette méthode en premier.

2. Utiliser les caractéristiques des transactions de la base de données pour effectuer des mises à jour atomiques.

3. À l'aide du verrouillage exclusif de fichier, lors du traitement d'une demande de commande, utilisez flock pour verrouiller un fichier. Seuls ceux qui obtiennent le verrouillage peuvent traiter la commande.

1. Utiliser les fonctionnalités de transaction Redis

Les transactions Redis sont des opérations atomiques, qui peuvent garantir que les données ne sont pas modifiées par d'autres processus simultanés pendant le traitement des commandes.

Exemple de code :

<?php
$http = new swoole_http_server("0.0.0.0", 9509);  // 监听 9509
 
$http->set(array(
  &#39;reactor_num&#39; => 2, //reactor thread num
  &#39;worker_num&#39; => 4  //worker process num
));
 
$http->on(&#39;request&#39;, function (swoole_http_request $request, swoole_http_response $response) {
  $uniqid = uniqid(&#39;uid-&#39;, TRUE);  // 模拟唯一用户ID
  $redis = new Redis();
  $redis->connect(&#39;127.0.0.1&#39;, 6379);  // 连接 redis
 
  $redis->watch(&#39;rest_count&#39;); // 监测 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(&#39;uniqids&#39;, $value);
    $redis->decr(&#39;rest_count&#39;);
    $replies = $redis->exec(); // 执行以上 redis 事务
 
   // 如果 rest_count 的值被其它的并发进程更改了,以上事务将回滚
    if(!$replies){
      echo "订单 {$value} 回滚".PHP_EOL;
    }
  }
  $redis->unwatch();
});
 
$http->start();

Utiliser ab test

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

2. Utiliser le verrouillage exclusif de fichier (mode de blocage)

En mode blocage, si un processus acquiert un verrou exclusif de fichier alors que d'autres processus occupent le verrou, le processus se bloquera et attendra que d'autres processus libèrent le verrou, acquièrent le verrou lui-même, puis continuent.

Exemple de code :

<?php
$http = new swoole_http_server("0.0.0.0", 9510);
 
$http->set(array(
  &#39;reactor_num&#39; => 2, //reactor thread num
  &#39;worker_num&#39; => 4  //worker process num
));
 
$http->on(&#39;request&#39;, function (swoole_http_request $request, swoole_http_response $response) {
 
  $uniqid = uniqid(&#39;uid-&#39;, TRUE);
  $redis = new Redis();
  $redis->connect(&#39;127.0.0.1&#39;, 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(&#39;uniqids&#39;, $value);
      $redis->decr(&#39;rest_count&#39;);
    }
 
   // 订单处理完成后,再释放锁
    flock($fp,LOCK_UN);
  }
  fclose($fp);
 
});
 
$http->start();

Utiliser ab test

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

Tutoriel recommandé : Tutoriel PHP

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn