詳しく説明してもらえますか? 一日中キューを聞いていて頭が痛くなりました。
返信内容:
まず、キューはリンクリストまたは配列を使用して実装できるデータ構造です。キューの特徴は、キューに入れられたデータが最初にキューから出てくることです。
しかし、トピックタグに Redis が含まれていることから、質問者は現在広く使用されている Message Queue (MQ) について聞きたいのだと思います。ここでのメッセージは単なるテキスト情報ではなく、シリアル化されたオブジェクトでもあります。現在、より一般的なオープン ソース メッセージ キュー システムには、Beanstalkd、RabbitMQ、Redis (キュー システムとして使用可能) などが含まれます。それらの中核機能は、まずシステム インターフェイスを通じてメッセージ データを順番にキューに入れることです (メッセージ データを一時的に保存します)。メモリ内に保存し)、必要に応じて、後続の処理のために挿入された順序で取り出して使用します。
私が以前構築した電子メール送信システムを例に挙げます。
このシステムは、外部に提供される HTTP プロトコルを使用してサービスを提供します。API アドレスは /api/msg.send です。ユーザーは、POST でこのアドレスを要求し、件名、本文、受信者の 3 つのパラメーターを渡すだけで電子メールを送信できます。
オプション 1: データベースなし、キューなし インターフェイスを要求するとき、コントローラーは sendmail または外部 smtp サーバーを直接呼び出して電子メールを送信し、送信全体HTTPリクエストの処理が待機状態になり、メール送信後、送信結果が返されます(送信プログラムが正常に呼び出された結果であり、実際のメール送信結果ではありません。実際の送信結果はメールログの解析が必要です) )
この解決策は最も単純で直接的です。通常は少量の電子メールを送信します。ただし、欠点も明らかです。
1. インターフェイスが呼び出されるときに、電子メール送信プロセス全体が同期的に実行されるためです。 、各リクエストは電子メール送信側の処理が完了するまで待機する必要があり、必然的に各インターフェイス呼び出しの待ち時間が増加します。
2. システム インターフェイスへの同時リクエストが多い場合、システムの可用性は Web サーバーの処理能力によって制限されるだけでなく、これらのリンクのいずれかの障害によっても完全に制限されます。システム全体がサービスを提供できなくなります。
3. 電子メール送信ソフトウェアが失敗し (SMTP 接続のタイムアウトなど)、特定のリクエスト中に電子メールの送信が失敗した場合、電子メールの内容は完全に失われ、保存されなくなります。システム上、自動再送信はできません。
オプション 2: キューの代わりにデータベースを使用する インターフェイスを要求する場合、送信される電子メール情報をデータベースに保存します。テーブル構造は次のとおりです。
id | 件名 | 受信者 | failed_times 次に、sent_at=0 && failed_times
オプション 1 と比較した改善点:
1. 電子メールの同期送信操作が削除され、インターフェース要求の応答が大幅に高速化されます。
2. 電子メールの送信に失敗した場合、再送信してもメールは失われません
3. システムは、メール送信側が完全に失敗した場合にもメール送信リクエストを受け付け、送信側が回復した後もメールの送信を続行できます。
しかし、まだ欠点もあります。
大量の同時実行または大量のデータがある場合 (1 つのリクエストに 100 万人の受信者が含まれる場合)、データベースの負荷が高くなります。高すぎると安定性に影響し、インターフェイスの応答時間も大幅に増加します (一度に 100 万件のレコードを書き込むのは冗談ではありません)
オプション 3: データベース + キューリクエスト インターフェイス中に、送信される電子メール情報は JSON 形式でキュー システムに保存されます。挿入される単一メッセージは次の形式になります。
{ "件名" : "今日は薬がありません" , "身体" : "自分の気持ち", "受信者" : "mengmeng@da.com"}今日のキューは基本的にメモリキューであり、データアクセスは非常に高速であり、瞬時に 100 万個のデータを書き込むことはもはや難しくありません。
その後、サーバー上で常駐プロセスタスク (ワーカー) を実行し、キュー内に新しいメッセージ (ジョブ、ここでは電子メール情報を指します) があるかどうかをリアルタイムで監視します。新しいメッセージが到着すると、キューからメッセージを削除し、電子メール送信側を呼び出して処理を完了します。メッセージが正常に送信された後、メッセージは破棄され、メッセージの内容がデータベースに挿入されます (オプション 2 と同じ)。送信が失敗した場合、メッセージはキューに戻され、60 秒後に取り出して処理されることを意味します。
このような改善により、システム全体のスループットと応答速度が大幅に向上し、同時にシステムの分散運用が可能となります。各ワーカープロセスを処理ノードとみなすことができ、ワーカーを複数のサーバーに分散させることで、システム全体の分散処理を実現することができます。
私の実際のプロジェクトでは、解決策 3 に基づいて多くの改善を加えました。また、システム全体は、Mailgun と Sendcloud の設計に似ています。安定したら、コードを Github にオープンソース化することを検討します。
この例は、キューの一般的な使用シナリオにすぎません。一般に、データベースの書き込み負荷を軽減する必要があるシナリオでは、メッセージ キューの使用を検討できます。場合によっては、分散処理が必要な場合もあります。非常に良い使用例です。
現在、ほとんどの言語には成熟したメッセージキュー処理コンポーネントがあり、さまざまなキューシステムを簡単に使用できます。たとえば、私がよく使用している
Laravel は、Beanstalkd、Amazon SQS、IronMQ、および Redis をネイティブにサポートしています。
不足がある場合は修正してください。ありがとうございます。
行列という言葉を聞いたことがありますか?先に来た人は先頭(列の先頭)に並び、後から来た人は後に続きます(列の最後尾)、列を離れるときは列の先頭から離れ、列に入る人はそれに続きます行列の最後尾はこちらです!実装に関しては、リンクされたリストと配列の両方が機能します。