システム設計におけるメッセージキュー
Hãy tưởng tượng một cửa hàng trực tuyến. Mỗi khi khách hàng đặt hàng, bạn cần thực hiện những việc sau:
- Xử lý thanh toán
- Cập nhật tồn kho
- Gửi email xác nhận
Việc thực hiện tất cả những điều này ngay lập tức, đặc biệt là trong giờ cao điểm, có thể làm chậm trải nghiệm của khách hàng.
Trong trường hợp này, có nhiều sự kiện ứng dụng và không thể xử lý tất cả cùng một lúc.
Tất nhiên, bạn có thể mở rộng quy mô máy chủ để xử lý số lượng lớn các sự kiện ứng dụng này, nhưng nếu không cần xử lý tất cả cùng một lúc, tốt hơn là đưa các sự kiện này vào hàng đợi để xử lý sau.
Kiến trúc cơ bản của hàng đợi tin nhắn
Hàng đợi tin nhắn là một thành phần lưu trữ trong bộ nhớ hỗ trợ giao tiếp bất đồng bộ. Nó hoạt động như một bộ đệm và phân phối các yêu cầu bất đồng bộ.
Kiến trúc cơ bản của hàng đợi tin nhắn khá đơn giản. Một dịch vụ đầu vào, được gọi là producer hoặc publisher, tạo và đăng tin nhắn lên hàng đợi. Các dịch vụ khác, được gọi là consumer hoặc subscriber, kết nối với hàng đợi và thực hiện các hành động được định nghĩa bởi tin nhắn.
Trong kịch bản thực tế, có thể có nhiều ứng dụng ghi vào hàng đợi và nhiều máy chủ đọc từ hàng đợi.
Quay lại ví dụ
Vì vậy, trong trường hợp này, thay vì xử lý ngay lập tức mỗi tác vụ, bạn có thể thêm chúng vào cuối hàng đợi và gửi từ hàng đợi này đến máy chủ.
- Đơn hàng được tạo: Chi tiết đơn hàng được đưa vào tin nhắn
- Tin nhắn được gửi: Tin nhắn được thêm vào hàng đợi
- Worker xử lý: Một quy trình khác (worker) lấy tin nhắn từ đầu hàng đợi và xử lý tác vụ
Ngoài ra, máy chủ xác nhận đã nhận và xử lý tin nhắn, và hàng đợi sẽ xóa nó để không gửi lần thứ hai.
Lợi ích của việc sử dụng hàng đợi tin nhắn
Lợi ích chính là việc tách biệt các sự kiện này, và với hàng đợi tin nhắn này, bạn có thể xử lý các sự kiện một cách bất đồng bộ. Bạn có thể đưa chúng vào hàng đợi cho đến khi có thể xử lý được.
Với hàng đợi tin nhắn, producer có thể đăng tin nhắn vào hàng đợi ngay cả khi consumer không thể xử lý.
Đồng thời, consumer có thể đọc tin nhắn từ hàng đợi ngay cả khi producer không khả dụng.
Một lợi ích lớn khác là tính bền vững. Nếu hàng đợi gặp sự cố, dữ liệu không bị mất vì nó được lưu trữ trên đĩa chứ không phải trong RAM.
Không có vấn đề gì nếu worker gặp sự cố trong khi đang xử lý tin nhắn. Tin nhắn vẫn còn trong hàng đợi và sẽ được lấy bởi một worker khác.
Hàng đợi tin nhắn cũng cung cấp khả năng mở rộng. Nếu có nhiều đơn hàng đột ngột, hàng đợi sẽ đơn giản là dài hơn. Bạn có thể thêm worker để xử lý tải bổ sung mà không ảnh hưởng đến website.
Các loại hàng đợi khác nhau
Có nhiều loại hàng đợi tin nhắn. Những loại phổ biến nhất là:
- FIFO (First In First Out): Giống như một hàng đợi thông thường, tin nhắn được xử lý theo thứ tự đến. Điều này quan trọng đối với việc như xử lý thanh toán.
- Hàng đợi ưu tiên: Một số tin nhắn có thể quan trọng hơn những tin nhắn khác. Chúng có thể được ưu tiên để xử lý sớm hơn.
Các trường hợp sử dụng phổ biến cho hàng đợi FIFO và hàng đợi ưu tiên
Trường hợp sử dụng hàng đợi FIFO
-
Hệ thống xử lý đơn hàng
- Lý do: Đơn hàng cần được xử lý theo thứ tự nhận, nên hàng đợi FIFO là tối ưu. Điều này đảm bảo công bằng và duy trì tính nhất quán của tồn kho.
-
Hệ thống đặt vé
- Lý do: Hàng đợi FIFO được sử dụng để duy trì nguyên tắc "ai đến trước được phục vụ trước". Điều này đảm bảo tính công bằng và minh bạch của hệ thống.
-
Xử lý log
- Lý do: Log entries được xử lý trong hàng đợi FIFO để duy trì chính xác trình tự thời gian của các sự kiện. Điều này giúp việc debug và kiểm toán dễ dàng hơn.
Trường hợp sử dụng hàng đợi ưu tiên
-
Hệ thống phản ứng khẩn cấp
- Lý do: Hàng đợi ưu tiên phù hợp khi cần xử lý các yêu cầu khẩn cấp (ví dụ: điều động xe cứu thương) một cách ưu tiên.
-
Hệ thống ticket hỗ trợ khách hàng
- Lý do: Hàng đợi ưu tiên được sử dụng để xử lý ưu tiên cho khách hàng quan trọng hoặc vấn đề khẩn cấp. Điều này giúp nâng cao sự hài lòng của khách hàng.
-
Lập lịch tác vụ trong hệ điều hành
- Lý do: Cần thực hiện ưu tiên các tác vụ quan trọng để tối ưu hóa hiệu suất hệ thống. Hàng đợi ưu tiên cho phép điều này.
Push vs Pull
Một số hàng đợi chờ worker yêu cầu tin nhắn (hàng đợi dựa trên pull), trong khi các hàng đợi khác chủ động gửi tin nhắn đến worker (hàng đợi dựa trên push).
Ví dụ
Dưới đây là một số ví dụ phổ biến về hàng đợi tin nhắn:
- RabbitMQ: Một hàng đợi đa năng phù hợp với nhiều trường hợp sử dụng.
- Kafka: Được xây dựng cho thông lượng cao và streaming dữ liệu thời gian thực. Lý tưởng cho logging và kiến trúc hướng sự kiện.
- Amazon SQS (Simple Queue Service): Dịch vụ hàng đợi được quản lý hoàn toàn do AWS cung cấp. Một dịch vụ có thể mở rộng và đáng tin cậy với các tính năng như hàng đợi trễ và hàng đợi thư chết.
Bonus: Các trường hợp sử dụng cụ thể của hàng đợi tin nhắn
-
Kiến trúc microservices
- Mô tả: Cho phép giao tiếp bất đồng bộ giữa các dịch vụ khác nhau, cải thiện tính linh hoạt và khả năng mở rộng của hệ thống.
-
Xử lý hàng loạt
- Mô tả: Được sử dụng để xử lý hiệu quả khối lượng lớn dữ liệu. Ví dụ: phù hợp cho phân tích dữ liệu và tạo báo cáo qua đêm.
-
Kiến trúc hướng sự kiện
- Mô tả: Được sử dụng để truyền các sự kiện giữa các thành phần khác nhau trong hệ thống. Điều này cải thiện khả năng phản ứng và tính linh hoạt của hệ thống.
-
Cân bằng tải
- Mô tả: Cải thiện hiệu suất và tính khả dụng của hệ thống bằng cách phân phối tác vụ cho nhiều worker.
-
Tích hợp đa nền tảng
- Mô tả: Hoạt động như một lớp trung gian để trao đổi dữ liệu giữa các stack công nghệ và nền tảng khác nhau.
-
Xử lý dữ liệu IoT
- Mô tả: Được sử dụng để xử lý và phân tích hiệu quả luồng dữ liệu từ nhiều thiết bị IoT.
Những trường hợp sử dụng này cho thấy hàng đợi tin nhắn đóng vai trò quan trọng trong nhiều tình huống khác nhau. Bằng cách chọn loại hàng đợi phù hợp, bạn có thể cải thiện đáng kể hiệu quả, độ tin cậy và khả năng mở rộng của hệ thống.
Bài viết này được dịch từ Message Queues in System Design.
システム設計におけるメッセージキュー
オンラインストアを想像してみてください。顧客が注文するたびに、以下のことを行う必要があります。
- 支払いを処理する。
- 在庫を更新する。
- 確認メールを送信する。
特にピーク時にこれらすべてを即座に行うと、顧客の体験が遅くなる可能性があります。
この場合、多数のアプリケーションイベントがあり、それらをすべて一度に処理することはできません。
もちろん、サーバーをスケールアップして、これらの大量のアプリケーションイベントを処理することもできますが、一度にすべてを処理する必要がない場合は、これらのイベントをキューに入れて後で処理する方が良いでしょう。
メッセージキューの基本アーキテクチャ
メッセージキューは、非同期通信をサポートするメモリに格納される永続的なコンポーネントです。バッファとして機能し、非同期リクエストを分散します。
メッセージキューの基本的なアーキテクチャは単純です。プロデューサーまたはパブリッシャーと呼ばれる入力サービスは、メッセージを作成してメッセージキューに公開します。コンシューマーまたはサブスクライバーと呼ばれる他のサービスは、キューに接続し、メッセージによって定義されたアクションを実行します。
実際のシナリオでは、キューに書き込む多くのアプリとキューから読み取る多くのサーバーが存在する可能性があります。
例に戻りましょう
したがって、この場合、各タスクを即座に処理する代わりに、キューの最後に追加し、このキューからサーバーに送信できます。
- 注文が行われた:注文の詳細がメッセージに入れられます。
- メッセージが送信された:メッセージがキューに追加されます。
- ワーカーが処理する:別のプロセス(ワーカー)がキューの先頭からメッセージを取り出し、タスクを処理します。
また、サーバーはメッセージを受信して処理したことを確認し、キューはそれを削除して2回目に送信されないようにします。
メッセージキューを使用する利点
主な利点は、これらのイベントを分離することであり、このメッセージキューにより、これらのイベントを非同期的に処理できます。処理できるようになるまで、それらをキューに入れることができます。
メッセージキューを使用すると、コンシューマーが処理できない場合でも、プロデューサーはメッセージをキューに投稿できます。
また、プロデューサーが利用できない場合でも、コンシューマーはキューからメッセージを読み取ることができます。
もう1つの大きな利点は、耐久性があることです。キューがクラッシュしても、データはRAMではなくディスクに保存されているため、失われることはありません。
ワーカーがメッセージの処理中にクラッシュしても問題ありません。メッセージはまだキューにあり、別のワーカーによって取得されます。
メッセージキューはスケーラビリティも提供します。注文が殺到した場合、キューは単に長くなります。Webサイトに影響を与えずに、ワーカーを追加して追加の負荷を処理できます。
さまざまなキュータイプ
メッセージキューには複数のタイプがあります。最も一般的なものは次のとおりです。
- FIFO(先入れ先出し):通常の行列と同じように、メッセージは到着順に処理されます。これは、支払い処理などにとって重要です。
- 優先度キュー:一部のメッセージは他のメッセージよりも重要な場合があります。これらを優先して、より早く処理されるようにすることができます。
FIFOキューと優先度キューの一般的なユースケース
FIFOキューのユースケース
-
注文処理システム
- 理由:注文は受信順に処理する必要があるため、FIFOキューが最適です。これにより、公平性が保たれ、在庫の整合性が維持されます。
-
チケット予約システム
- 理由:「先着順」の原則を維持するために、FIFOキューが使用されます。これにより、システムの公平性と透明性が確保されます。
-
ログ処理
- 理由:イベントの時系列を正確に維持するために、ログエントリはFIFOキューで処理されます。これにより、デバッグや監査が容易になります。
優先度キューのユースケース
-
緊急対応システム
- 理由:緊急度の高い要求(例:救急車の派遣)を優先的に処理する必要があるため、優先度キューが適しています。
-
カスタマーサポートチケットシステム
- 理由:重要な顧客や緊急の問題を優先的に処理するために、優先度キューが使用されます。これにより、顧客満足度が向上します。
-
オペレーティングシステムのタスクスケジューリング
- 理由:システムの効率を最大化するために、重要なタスクを優先的に実行する必要があります。優先度キューはこれを可能にします。
プッシュ対プル
一部のキューはワーカーがメッセージを要求するのを待ち(プルベースのキュー)、他のキューはメッセージをワーカーに積極的に送信します(プッシュベースのキュー)。
例
メッセージキューのいくつかの一般的な例を次に示します。
- RabbitMQ:多くのユースケースに適した汎用的なキューです。
- Kafka:高スループットとリアルタイムのデータストリーミング用に構築されています。ロギングやイベント駆動型アーキテクチャなどに最適です。
- Amazon SQS(Simple Queue Service):AWSが提供する完全に管理されたクラウドベースのキューサービスです。遅延キューとデッドレターキューなどの機能を備えた、スケーラブルで信頼性の高いサービスです。
ボーナス:メッセージキューの具体的なユースケース
-
マイクロサービスアーキテクチャ
- 説明:異なるサービス間の非同期通信を可能にし、システムの柔軟性と拡張性を向上させます。
-
バッチ処理
- 説明:大量のデータを効率的に処理するために使用されます。例えば、夜間のデータ分析や報告書生成などに適しています。
-
イベント駆動型アーキテクチャ
- 説明:システム内のさまざまなコンポーネント間でイベントを伝播させるために使用されます。これにより、システムの反応性と柔軟性が向上します。
-
負荷分散
- 説明:タスクを複数のワーカーに分散させることで、システムのパフォーマンスと可用性を向上させます。
-
クロスプラットフォーム統合
- 説明:異なる技術スタックやプラットフォーム間でデータを交換するための中間層として機能します。
-
IoTデータ処理
- 説明:多数のIoTデバイスからのデータストリームを効率的に処理し、分析するために使用されます。
これらのユースケースは、メッセージキューがさまざまな状況で重要な役割を果たすことを示しています。適切なキュータイプを選択することで、システムの効率性、信頼性、スケーラビリティを大幅に向上させることができます。
この記事は、Message Queues in System Designから翻訳されました。
All rights reserved