ホームページ  >  記事  >  バックエンド開発  >  PHPメッセージキューの実装と応用を詳しく解説(フローチャート付き)

PHPメッセージキューの実装と応用を詳しく解説(フローチャート付き)

藏色散人
藏色散人転載
2022-10-27 16:00:095279ブラウズ

#メッセージ キューの概念、原理、実装

コンセプト

    キュー構造のミドルウェア
  • メッセージをすぐに消費する必要はありません
  • コンシューマまたはサブスクライバによって順番に消費されます

##基本的なフローチャートは次のとおりです

プロセス

  • PHPメッセージキューの実装と応用を詳しく解説(フローチャート付き)

アプリケーション シナリオ

冗長性
  • デカップリング
  • トラフィックのピークカット
  • ##非同期通信
  • #実装方法
mysql: 信頼性が高く、遅い

redis: 大きいメッセージ パケットの処理が速い、遅い

メッセージ システム: 信頼性が高くプロフェッショナル
  • メッセージ トリガー メカニズム
Infiniteループ方式、障害発生時に復旧が間に合わない

スケジュールされたタスク: 圧力均等化、ただし処理能力に上限あり

デーモンプロセス方式
  • デカップリング (注文と配送システム)
#スケジュールされたタスクを使用したアーキテクチャ設計 1

    ##分散処理システムを利用して処理する場合、現在のデータベースで処理対象の注文のステータスを2に更新し、処理完了後にステータスを1に設定することができます。毎回更新するデータの数を指定します

  • PHPメッセージキューの実装と応用を詳しく解説(フローチャート付き)

  • トラフィック削減 (Redis はフラッシュ セールを実装します)
  • キューを使用しますデータ構造
  • lpush/rpush データをリストに追加します
lpop/rpop リストからデータを削除し、削除された値を取得します

ltrim 指定された値を保持します間隔

llen 内の要素 リストの長さを取得します
  • lset インデックスによってリストの値を設定します

    lindex インデックスによってリストの値を取得します
    • lrange 指定された範囲を取得します。要素
    • ## は次のように図示されます
    • ##コード フローは次のとおりです。以下に続きます
    • フラッシュ キル プログラムはリクエストを redis(uid, time) に書き込みます
  • redis リスト ストレージの長さを確認します (存在する場合)。 10 を超えると、直接破棄されます
    PHPメッセージキューの実装と応用を詳しく解説(フローチャート付き)

  • 無限ループを通じて Redis データを読み取り、データベースに保存します##
// 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);
    }}
    • 上記のコードの同時実行性が大きすぎる場合、売られすぎの状況が発生します。このとき、ファイル ロックまたは Redis 分散ロックを使用して制御できます。まず製品を Redis リストに追加し、rpop を使用して取得します。
    • 具体的なアイデアと疑似コードは次のとおりです
    •   // 先将商品放入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

    • #アーキテクチャと原理
  • ここで、P はプロダクションを表します。または、X はスイッチ (チャネル)、C はコンシューマを表します

  • 簡単な使い方

      // 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();
      }
  • 以上がPHPメッセージキューの実装と応用を詳しく解説(フローチャート付き)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

    声明:
    この記事はlearnku.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。