メインコンテンツに移動
デベロッパーのためのクラウド活用方法

Amazon SQS と処理の重複 後編 ~ FIFO キューの特徴

2024-03-04 | Author : 杉本 圭太

はじめに

テクニカルインストラクターの杉本圭太です !
最近読んで面白かった漫画は「アンタイトル・ブルー」です。

Amazon SQS と処理の重複 前編 ~ 可視性タイムアウトの役割 で Amazon Simple Queue Service (SQS) の概要、そして可視性タイムアウトの役割やスタンダードキューの特徴を紹介しました。後編では FIFO キューの特徴や機能を学んでいきましょう φ(•ᴗ•๑)

今回も自作した図を交えて解説していきます。全体概要はこちらです。


X ポスト » | Facebook シェア » | はてブ »

Japanese diagram illustrating the message grouping and ordering in an AWS SQS FIFO queue, showing how messages are grouped by MessageGroupId and processed by producers and consumers.

builders.flash メールメンバー登録

builders.flash メールメンバー登録で、毎月の最新アップデート情報とともに、AWS を無料でお試しいただけるクレジットコードを受け取ることができます。 
今すぐ登録 »

1. FIFO キューの特徴

Amazon SQS ではキューを作成するときにスタンダードキューか FIFO キューのどちらかのタイプを選択します。キューのタイプは作成後に変更できません。

FIFO キューは前回紹介したスタンダードキューと同じ API でメッセージの送受信をするため、使い方はスタンダードキューと似ている部分が多いです。

  • プロデューサーが SendMessage リクエストで、キューにメッセージを送る

  • コンシューマーが ReceiveMessage リクエストで、キューからメッセージを取り出す

  • キューから取り出したメッセージに可視性タイムアウトが設定できる

  • コンシューマーが DeleteMessage リクエストで、処理が完了したメッセージをキューから削除する


しかし キュータイプ の説明に記載がある通り、配信順序、メッセージ配信時の重複の有無、スループットなどに違いがあります。その中で重要な用語を説明します。

1-1. First-In-First-Out (FIFO)

First-In-First-Out (FIFO) は「先入れ先出し」とも呼ばれます。キューのタイプの名前にもなっている通り FIFO キューを使用することで、キューに送信された順にメッセージを取得できます。スタンダードキューでは送信順にメッセージを取得できる保証はありません。

2020 年に公開された Application Integration Using Queues and Messages というブログ内にあるこちらの比較画像がわかりやすいです。

Diagram comparing Amazon SQS Standard and FIFO queues, illustrating message flow from producer to consumer. The Standard SQS shows best effort ordering with possible message duplicates, while the FIFO queue ensures exactly-once message delivery and preserved order.

1-2. Exactly-Once

一般的な FIFO の特性とは関係無く、あくまで Amazon SQS の仕様として FIFO キューは Exactly-Once という特徴を持っています。Exactly-Once は「1 回限り」や「正確に 1 度」などと訳されることもありますが、FIFO キューの場合では「(可視性タイムアウトが切れない限り) 1 つのメッセージはキューから重複して配信されない」という意味です。

前編でスタンダードキューは At-Least-Once であるため、ReceiveMessage リクエストで可視性タイムアウト切れとは関係なく同じメッセージが複数回配信されてしまう可能性があると紹介しましたが、FIFO キューではそうならないように設計されています。しかし可視性タイムアウトの期限が切れるとスタンダードキューと同様に再度メッセージは配信されるため、FIFO キューを使用しただけで処理重複が完全になくなる訳ではない点はご注意ください。

FIFO や Exactly-Once というキューの特徴を確認しましたが、次からは API で FIFO キューを扱うために知っておくべき機能を説明します。

2. FIFO キューでのメッセージ送信 (SendMessage)

FIFO キューへメッセージを送信する場合はスタンダードキューと同じく SendMessage リクエストを使用しますが、FIFO キューではスタンダードキューで使用しないパラメーターを 2 つ意識する必要があります。

※ 複数のメッセージを 1 度のリクエストで送信したい場合は SendMessageBatch リクエストを使用できますが、こちらも FIFO キューで使用する場合は同様の考慮が必要です。

2-1. MessageGroupId (メッセージグループ ID)

FIFO キューへの送信リクエストでは、メッセージごとに MessageGroupId というパラメーターを必ず指定しなければなりません。つまりメッセージはキューへ送信されて保存されると、キューの中のとあるメッセージグループに属します。

このメッセージグループの特徴を挙げます。

  • キューへ送信する時に任意の MessageGroupId を指定するため、事前にキューに設定するものではない

  • 1 つの FIFO キューの中に複数のグループが存在しても良い

  • 同じグループのメッセージは、そのグループに送信された順にキューから配信されていく

  • グループが異なれば、同じキューでも送信された順にメッセージが処理されるとは限らない


こちらの図では 1 つの FIFO キューに、MessageGroupId が A のメッセージと MessageGroupId が B のメッセージを送信しています。

FIFO キューでメッセージ送信

A diagram in Japanese illustrating how to send a message using the AWS SQS FIFO queue, including the requirement to specify a MessageGroupId. The visual shows producers and message flow into the SQS FIFO queue.

A Japanese-language diagram illustrating message sending using AWS SQS FIFO queues. It shows two producers (X and Y) and explains how messages are saved within a message group (Group A), with notes about the MessageGroupId not needing to be predetermined.

Japanese diagram showing message group handling in an AWS SQS FIFO queue, illustrating producers sending messages to different message groups (Group A and Group B).

A diagram in Japanese showing how messages are grouped and ordered in an AWS SQS FIFO queue. It illustrates two producers (X and Y) sending messages to message groups A and B, with a focus on the order and grouping of messages within the FIFO queue.

送信時はメッセージごとに MessageGroupId を指定

もちろん 1 つのキューの中でメッセージのグループは 1 つだけにしても良いです。

複数のグループを扱うことでメッセージグループ ID がどのように機能するかは FIFO キューでのメッセージ受信 (ReceiveMessage) で説明しますので、まずこの時点では「送信時はメッセージごとに MessageGroupId を指定する必要がある」とだけ認識できれば OK です !

2-2. MessageDeduplicationId (メッセージ重複排除 ID)

FIFO キューでは送信時の重複を緩和するため、メッセージごとに MessageDeduplicationId というパラメーターを設定します。
この仕組みがあることで、キュー側では 5 分の間に MessageDeduplicationId が同じメッセージを何度受け取っても、キュー内には 2 度目以降のメッセージが保存されないように制御されます。ただし 2 度目以降のリクエストもレスポンスは成功として返します。また、重複排除のスコープはキュー単位かメッセージグループ単位かで選択できます。

こちらの図は MessageDeduplicationId を b1 という値にして 2 度 SendMessage リクエストしています。

FIFO キューで MessageDeduplicationId を指定してメッセージ送信

A Japanese-language diagram explaining how to specify MessageDeduplicationId when sending a message to an Amazon SQS FIFO queue. The diagram illustrates a producer sending a message with MessageDeduplicationId to the SQS FIFO queue.

A Japanese-language diagram explaining the use of MessageDeduplicationId in AWS SQS FIFO Queue. The diagram illustrates how messages are saved within a group and depicts connection issues that may prevent a producer from receiving a response.

A Japanese-language diagram illustrating how to specify MessageDeduplicationId when sending messages to an Amazon SQS FIFO queue, including message structure and deduplication behavior.

A Japanese-language diagram explaining how MessageDeduplicationId works in an AWS SQS FIFO queue, showing message grouping, deduplication within 5 minutes, and response handling.

1 つのメッセージしかキュー内に保存されない

結果として 1 つのメッセージしかキュー内に保存されていません。

ちなみに FIFO キュー自体の設定で ContentBasedDeduplication を true にしておくと、送信リクエストで MessageDeduplicationId に任意の値を指定しなくても、自動で MessageBody からハッシュ値を生成して MessageDeduplicationId に設定してくれます (MessageAttributes はハッシュ値の生成に使用されません)。

3. FIFO キューでのメッセージ受信 (ReceiveMessage)

ここからは FIFO キュー内にグループを指定して保存されたメッセージをコンシューマーが受け取る場合の動作を確認しましょう。

重要な点を挙げるとすると、コンシューマーはメッセージを受け取る時にグループを指定できません (ReceiveMessage リクエストで MessageGroupId は指定できないため)。そのため ReceiveMessage リクエストの結果がどうなるかを理解しておくことが、FIFO キューを使いこなす鍵となります。この動作を理解しやすくしてもらうため、キューの状況などによって ReceiveMessage リクエストの結果がどうなるのかを、いくつかのパターンに分けて整理しました。

3-1. 1 つの Group から 1 つのメッセージを受信

まずは FIFO キューの挙動を理解するため、キューにメッセージグループが 1 つ、コンシューマーはメッセージを 1 つずつ取得していく場合の動作を確認します。

ここで押さえて欲しい点は「FIFO キューでは取得中のメッセージがあるグループからは、後続のメッセージが取り出せない」です。
つまりキューの中の Group A のメッセージが 1 つ取得された後は、そのメッセージを DeleteMessage リクエストで削除するか、可視性タイムアウトが切れるまでは Group A からメッセージが取り出せません。

FIFO キューで 1 つの Group から 1 つのメッセージを受信

FIFO キューでの First-In-First-Out は「取り出したら次」ではなく「メッセージの処理が完了したら次」という意味で捉えていただくとわかりやすいかもしれません。

Japanese diagram illustrating how a message is received from a group in an AWS SQS FIFO queue, with labeled messages, consumers, and step explanations.

AWS SQS FIFOキューにおける1つのグループからのメッセージ受信を示した日本語のダイアグラム。複数メッセージを持つGroup A、可視性タイムアウト、メッセージ取得のプロセスが図示されています。

Diagram in Japanese explaining message retrieval from a group in an AWS SQS FIFO queue, illustrating how only one message can be received at a time from a group and subsequent messages are not accessible until the previous one is processed.

Diagram in Japanese illustrating the process of deleting a message from an AWS SQS FIFO queue by specifying the ReceiptHandle, showing message flow and consumer interactions.

Diagram in Japanese illustrating the process of receiving one message from a group in an AWS SQS FIFO queue. The diagram shows message flow and architecture components, including consumers, message group, and a ReceiveMessage request, with explanatory notes in Japanese.

Diagram in Japanese illustrating how a single message is received from a group in an AWS SQS FIFO queue, showing message order and visibility timeout with consumer processes.

3-2. 1 つの Group から複数のメッセージを受信

スタンダードキューでも可能ですが、ReceiveMessage のリクエストでは MaxNumberOfMessages パラメーターを指定して、1 度に取得できる最大メッセージ数を指定できます。

この場合も「FIFO キューでは取得中のメッセージがあるグループからは、後続のメッセージが取り出せない」ため、コンシューマー X が Group A から 3 つのメッセージを取得した場合は、3 つ全てが DeleteMessage リクエストで削除か可視性タイムアウト切れになるまで Group A から後続のメッセージは取り出せません。

FIFO キューで 1 つの Group から複数のメッセージを受信

ここまではメッセージグループが 1 つしかない場合でしたが、次からはメッセージグループが複数ある場合の動作です。

Diagram in Japanese illustrating the process of receiving multiple messages from a single group in an AWS SQS FIFO queue. Shows message grouping, message identifiers, and a consumer making a ReceiveMessage request with MaxNumberOfMessages parameter.

Diagram explaining how messages are received from a single group in an AWS SQS FIFO queue, with visual steps and Japanese labels, including consumer X and Y and message visibility timeout settings.

Diagram in Japanese showing the process of deleting messages from an AWS SQS FIFO queue for a single group, including consumer actions and message state transitions.

A Japanese-language diagram illustrating the process of receiving multiple messages from a single group in an AWS SQS FIFO queue. The image explains message ordering and visibility with labeled consumers, message groups, and flow annotations.

3-3. 複数の Group がある中で 1 つの Group から複数のメッセージを受信

すでに書きましたがコンシューマーはメッセージを受け取る時にグループを指定できないため、FIFO キューに複数のメッセージグループがある場合はどうなるのでしょうか ?

実は状況によって「必ずこうなる」とは言い切れないため、「こんなこともあるよ」という例を紹介します。

コンシューマーが 1 リクエストで複数メッセージを取得しようとした場合、キューから複数のグループのメッセージを取得することもありますが、Amazon SQS の FIFO キューではできるだけ同じメッセージグループのメッセージを返すように設計されています。

Group A に 2 つのメッセージ、Group B に 4 つのメッセージがあり、コンシューマー X が最大 3 つのメッセージを取得するリクエストをすると、Group B から 3 つメッセージが取得されることもあります。

FIFO キューで複数の Group の内 1 つの Group から複数のメッセージを受信

Diagram in Japanese explaining how to receive multiple messages from a single group within multiple groups in an AWS SQS FIFO queue. Shows message groups A and B with message distribution, and consumers X, Y, and Z. Includes notes about 'ReceiveMessage' request and message group behavior.

A Japanese-language diagram illustrating message retrieval from a FIFO queue in Amazon SQS, showing multiple message groups (Group A and Group B) and how consumers receive messages from one group. The diagram includes messages, groups, and consumers, with explanatory Japanese text.

取得中のメッセージがない Group A からメッセージを受信

その後 コンシューマー Y がメッセージの取得リクエストをすると、取得中のメッセージがない Group A からメッセージを受け取れます。

Diagram in Japanese showing how to receive multiple messages from a single group in an AWS SQS FIFO queue, including message grouping, consumers, and receive message process with MaxNumberOfMessages setting.

A Japanese-language diagram illustrating message retrieval from multiple groups within an AWS SQS FIFO queue. The diagram depicts consumer servers receiving multiple messages from Group A and Group B, demonstrating FIFO processing and group-specific message consumption logic.

取得中のメッセージがあり、キュー内に他の Group がない場合

Group A も Group B も取得中のメッセージがあり、キュー内に他の Group がない場合はしばらくキューからメッセージを受け取れません。ただし、1 リクエストで必ず 1 つのグループのみとは限りません。

Diagram in Japanese showing the process of receiving multiple messages from only one group in an AWS SQS FIFO queue, including visuals of message grouping, consumers, and explanatory notes about message retrieval behavior.

取得中のメッセージがない Group A からメッセージを受信

その後 コンシューマー Y がメッセージの取得リクエストをすると、取得中のメッセージがない Group A からメッセージを受け取れます。

3-4. 複数の Group から複数のメッセージを受信

1 つ前のパターンと同様の条件で、Group A に 2 つのメッセージ、Group B に 4 つのメッセージがあり、コンシューマー X が最大 3 つのメッセージを取得するリクエストをしていますが、Group A から 2 つのメッセージ、Group B から 1 つのメッセージが取得されることもあります。

この図は、AWS SQS FIFOキューで複数のグループ(Group AとGroup B)から複数のメッセージを受信するプロセスを示しています。MaxNumberOfMessages: 3、MessageGroupIdは指定できません、という注意書き付きで、コンシューマーXからReceiveMessageリクエストが送信される様子が描かれています。  

SQS FIFOキューで複数のグループから複数のメッセージを同時にコンシューマーが受信する仕組みを説明する日本語の図です。各グループに属するメッセージの並びや取得パターンが示されています。

Amazon SQS の FIFO キューではできるだけ同じメッセージグループのメッセージを返すように設計されている

このように取得対象になったメッセージから同じグループのメッセージが送信順に取得されていますが、そのグループのメッセージ数がリクエストの MaxNumberOfMessages の数より少ない場合は、レスポンスに他のグループのメッセージも含まれています。

ただし Amazon SQS の FIFO キューではできるだけ同じメッセージグループのメッセージを返すように設計されているため、保証はないですが「Group A から 1 つのメッセージ、Group B から 2 つのメッセージ」のように、同じグループ内で最大数まで取得できていないのに複数のグループのメッセージが取得できるようなレスポンスになることは少ないと考えられます。


FIFO キューでのメッセージ受信パターンをいくつか確認しましたが、確実に 1 つずつメッセージを処理していきたいか、グループ単位でさえ順番に並んでいれば並列処理していけるなど、要件によってメッセージグループ ID の数やコンシューマーの数の設計が変わってくるということを理解しておきましょう !

4. その他の FIFO キューにしかない機能

最後におまけとして、スタンダードキューには存在しない機能を 2 つ紹介します。

4-1. 高スループットモード

スタンダードキューには明示的なクォータの制限はありませんが、FIFO キューでは現時点で SendMessageReceiveMessageDeleteMessage の 3 つの API はそれぞれ秒間 300 トランザクションまでのサポートです。(それぞれの API で 1 リクエストに複数メッセージを処理させれば、最大で秒間 3000 メッセージがサポートされています)

しかし FIFO キューは 高スループットモード に設定することで、クォータの引き上げ申請をしなくてもさらに高いスループットがサポートされています。リージョンによって上限は異なりますので、詳細な値は SQS のクォータ を確認ください。

高スループットモードを使用する場合の制約としては以下などがあるため、使用する場合はドキュメントを確認してください。

  • SendMessage リクエストで指定する MessageDeduplicationId の重複排除スコープはメッセージグループ単位

  • キューに設定できる FifoThroughputLimit はメッセージグループ単位

また、 高スループットモード のドキュメントには Amazon SQS が内部でどのようにパーティションを管理しているかも記載されていますので、興味がある方はぜひ !

4-2. ReceiveRequestAttemptId (受信リクエスト試行 ID)

必須のパラメーターではないですが、ReceiveMessage リクエストで ReceiveRequestAttemptId を指定すると、リクエストは成功してもレスポンスの受け取り時に失敗した場合などで、可視性タイムアウト切れを待たずに同じメッセージを再取得できます。

可視性タイムアウトを長めに設定していた場合は、レスポンスの受け取りを失敗するとリトライまでに時間がかかりすぎることを防げます。1 度目のリクエストから同じ ReceiveRequestAttemptId が 5 分以内である制約や、使い方を間違えると同じメッセージを重複して受け取る可能性もあるため注意が必要ですが、要件に合いそうであればドキュメントを確認してみてください。

FIFO キューで ReceiveRequestAttemptId を使用してメッセージを受信

Diagram showing how ReceiveRequestAttemptId is used to receive messages from an Amazon SQS FIFO queue, with examples of message groups and consumer requests. Text in Japanese.
Japanese diagram explaining how ReceiveRequestAttemptId and message visibility timeout work in AWS SQS FIFO Queues, showing message groups, visibility states, and consumer interactions.
AWS SQS FIFOキューでReceiveRequestAttemptIdを利用してメッセージを受信する流れを示した日本語の図解。グループAとグループBのメッセージ、MaxNumberOfMessagesおよびReceiveRequestAttemptIdのリクエスト例が描かれています。
AWS SQS FIFOキューでReceiveRequestAttemptIdを利用してメッセージを取得する流れを説明した日本語の図解。複数のグループに分かれたメッセージの処理や、可視性タイムアウト内での再取得の仕組みが視覚的に示されています。

5. おわりに

Amazon SQS の FIFO キューの特徴である First-In-First-Out や Exactly-Once だけでなく、API にどんなパラメーターがあり、どんな役割をするのかなども含めた説明をしました。この部分を理解できれば FIFO キューを使用すると部分的に重複緩和ができるという知識を踏まえて、適切に FIFO キューを活かしたシステム設計ができるはずです。

このようにテクニカルインストラクターは、自学だけではつまずきやすい部分などを含め、みなさんにより AWS を理解してもらいやすくなる工夫を日々行いながら クラスルームトレーニング を提供しております !

質問もリアルタイムでできるため分からない部分はとことんお付き合いしますし、ほとんどのコースには演習の時間も多くあるため学んだ内容を AWS 環境で実践できます !

AWS のトレーニングについてもっと知りたい方は、以下の連載記事も参考にどうぞ。


これまで自分で勉強してきたけど AWS を体系的に学ぶことでもっと詳しくなって業務で活用したい ! という方はぜひ AWS のトレーニングを受講してみてください !

筆者プロフィール

杉本 圭太
アマゾン ウェブ サービス ジャパン合同会社
トレーニングサービス本部 テクニカルインストラクター

テクニカルインストラクターとして、知識をつけることが目的ではなく実際に業務で活用できる力を得ることを目指したトレーニングを提供しています。自分自身が新しいことを知るのが好きなので、「AWS を知るのは面白い ! もっと学んでみよう !」と多くの方に感じてもらえる工夫を常に考えながら活動しています。

A person participates in a pottery workshop, smiling while shaping clay on a pottery wheel.