Maison >développement back-end >tutoriel php >Explication détaillée de la mise en œuvre et de l'application de la file d'attente de messages PHP (avec organigramme)

Explication détaillée de la mise en œuvre et de l'application de la file d'attente de messages PHP (avec organigramme)

藏色散人
藏色散人avant
2022-10-27 16:00:095346parcourir

Le concept, le principe et la mise en œuvre de la file d'attente des messages

Concept

  • Un middleware de la structure de la file d'attente
  • Pas besoin de consommer les messages immédiatement
  • Consommation dans l'ordre par les consommateurs ou les abonnés

Le L'organigramme de base est le suivant : implémentation

  • mysql : Fiable, lente
    Explication détaillée de la mise en œuvre et de lapplication de la file dattente de messages PHP (avec organigramme)redis : traitement rapide et lent des paquets de messages volumineux
Système de messagerie : fiable, hautement professionnel

    Mécanisme de déclenchement des messages
  • Méthode de boucle infinie, l'échec ne peut pas être effectué à temps Restauration
  • Tâches planifiées : pression uniformément répartie , mais avec une limite supérieure sur la capacité de traitement
  • Approche démon

Découplage (système de commande et de livraison)

  • Conception de l'architecture 1 Adopter des tâches planifiées

Lors de l'utilisation du système de traitement de distribution pour le traitement, mettre à jour le statut de la commande qui doit être traitée dans la base de données actuelle à 2 et définir le statut à 1 une fois le traitement terminé

    Vous pouvez spécifier le nombre de données à mettre à jour à chaque fois
  • Affûtage du trafic (redis implémente les ventes flash)

Utilisez la structure de données de file d'attente

  • lpush/rpush pour mettre les données dans la liste


    lpop/rpop pour supprimer les données de la liste et obtenir la valeur suppriméeExplication détaillée de la mise en œuvre et de lapplication de la file dattente de messages PHP (avec organigramme)

    ltrim Éléments réservés dans la plage spécifiée
  • llen Récupère la longueur de la liste

    lset Définit la valeur de la liste par index
  • lindex Récupère la valeur dans la liste par index

    lrange Récupère les éléments de la plage spécifiée

Le schéma est le suivant

    • Le flux de code est le suivant
    • Le programme flash kill écrit la requête dans redis(uid, time)
    • Vérifiez la longueur de stockage de la liste redis , si plus de 10 sont directement supprimés
    • Lisez les données Redis via une boucle infinie et stockez-les dans la base de données
    • // Spike.php 秒杀程序if(Redis::llen('lottery') <pre class="brush:php;toolbar:false">// Warehousing.php 入库程序while(true){
          $user = Redis::rpop('lottery');
          if (!$user || $user == 'nil') {
              sleep(2);
              continue;
          }
          $user_arr = explode($user, '%');
          $insert_user = [
              'uid' => $user_arr[0],
              'time' => $user_arr[1]
          ];
          $res = DB::table('lottery_queue')->insert($insert_user);
          if (!$res) {
              Redis::lpush('lottery', $user);
          }}
  • Si la concurrence dans le code ci-dessus est trop grande, il y aura des situations de survente. À ce stade, vous pouvez utiliser des verrous de fichiers ou des verrous distribués Redis pour le contrôle. Mettez d'abord les produits dans la liste Redis et utilisez rpop, si vous ne pouvez pas l'obtenir, cela signifie qu'il est épuisé
    Explication détaillée de la mise en œuvre et de lapplication de la file dattente de messages PHP (avec organigramme)

  • . L'idée spécifique et le pseudo code sont les suivants
  •   // 先将商品放入redis中
      $goods_id = 2;
    
      $sql = select id,num from goods where id = $goods_id;
      $res = DB::select($sql);
      if (!empty($res)) {
          // 也可以指定多少件
          Redis::del('lottery_goods' . $goods_id);
          for($i=0;$i<pre class="brush:php;toolbar:false">  // 开始秒杀
      $count = Redis::rpop('lottery_goods' . $goods_id);
      if (!$count) {
          // 商品已抢完
          ...
      }
    
      // 用户抢购队列
      $user_list = 'user_goods_id_' . $goods_id;
      $user_status = Redis::sismember($user_list, $user_id);
      if ($user_status) {
          // 已抢过
          ...
      }
    
      // 将抢到的放到列表中
      Redis::sadd($user_list, $uid);
      $msg = '用户:' . $uid . '顺序' . $count;
      Log::info($msg);
      // 生成订单等
      ...
      // 减库存
      $sql = update goods set num = num -1 where id = $goods_id and num > 0; // 防止超卖
      DB::update($sql)
      // 抢购成功

    • rabbitmq

    • Architecture et principe

    • où P représente le producteur et X est le commutateur (canal), C signifie consommateur

    Simple à utiliser
  // Send.php
  require_once __DIR__.'/vendor/autoload.php';

  use PhpAmqpLib\Connection\AMQPStreamConnection;
  use PhpAmqpLib\Message\AMQPMessage;

  $connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');

  // 创建通道
  $channel = $connection->channel();
  // 声明一个队列
  $channel->queue_declare('user_email', false, false, false, false);
  // 制作消息
  $msg = new AMQPMessage('send email');
  // 将消息推送到队列
  $channel->basic_publish($msg, '', 'user_email');

  echo '[x] send email';

  $channel->close();
  $connection->close();
  // Receive.php
  require_once __DIR__.'/vendor/autoload.php';

  use PhpAmqpLib\Connection\AMQPStreamConnection;
  use PhpAmqpLib\Message\AMQPMessage;

  $connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');

  //创建通道
  $channel = $connection->channel();

  $channel->queue_declare('user_email', false, false, false, false);

  // 当收到消息时的回调函数
  $callback = function($msg){
      //发送邮件
      echo 'Received '.$msg->body.'\n';
  };

  $channel->basic_consume('user_email', '', false, true, false, false, $callback);

  // 保持监听状态
  while($channel->is_open()){
      $channel->wait();
  }
  • 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:
    Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer