46. SQSは1台のキューではない — 冗長格納が生む at-least-once とベストエフォート順序
SQSの「キュー」の正体は複数AZにまたがるサーバー群への冗長格納です。この物理的な事実から、なぜ同じメッセージが2回届き、なぜ順序が保証されず、なぜ1回のReceiveで全部が返ってこないのかまでを、上から下へ図で追っていきます。
① SendMessageのACKは「複数AZに書き終えた」の合図
- 公式の言い回し:「When you send a message using SendMessage, Amazon SQS redundantly stores the message in multiple availability zones (AZs) before acknowledging it.」
- この冗長性の目的:「no single computer, network, or AZ failure can render the messages inaccessible」(単一のコンピュータ・ネットワーク・AZ障害でメッセージが失われない)。
ACKが返った時点で、メッセージは1台のサーバーではなく複数AZの複数サーバーにコピーされています。SQSの「キュー」とは、この分散した格納の集合体に付いた論理的な名前にすぎません。
② 「複数コピー」がそのまま at-least-once とベストエフォート順序になる
- 公式:「Standard queues ensure at-least-once message delivery, but due to the highly distributed architecture, more than one copy of a message might be delivered, and messages may occasionally arrive out of order.」
- ただしSQSは無秩序ではなく「best-effort attempt to maintain the order in which messages are sent」(送信順を保とうとはする)。あくまで保証ではない。
- 重複の具体的メカニズム(削除伝播ラグ)は公式が明言していないため「可能性」として提示。公式が断定しているのは「highly distributed architecture の帰結として複数コピーが配信されうる」ことまで。
at-least-once も順序の乱れも、SQS特有の欠陥ではなく「複数の場所に冗長に置いた」ことの直接の帰結です。DynamoDB編・Lambda編で見た「分散させると可用性は上がるが、代わりに一貫性(ここでは重複ゼロ・厳密順序)を諦める」という同じトレードオフが、ここでも効いています。だから受信側は冪等に作る(Lambda編で既習)——重複は例外ではなく仕様です。
③ ショートポーリング — サーバーの「一部」しか見ないから取りこぼす
- 公式:「Amazon SQS samples a subset of its servers (based on a weighted random distribution) and returns messages from only those servers. Thus, a particular ReceiveMessage request might not return all of your messages.」
- 「if you keep consuming from your queues, Amazon SQS samples all of its servers, and you receive all of your messages.」(叩き続ければ全サーバーが対象になり、いずれ全部届く)
- キュー内が1,000件未満なら次のリクエストで返る、とも明記。
- ショートポーリングになる条件は2通り:ReceiveMessage呼び出しで WaitTimeSeconds=0 を指定するか、指定なしでキュー属性 ReceiveMessageWaitTimeSeconds が0(既定)の場合。
①で冗長格納した結果、メッセージは多数のサーバーに散らばっています。ショートポーリングはそのうち一部をランダムに覗くだけなので、1回のReceiveで全メッセージが返らないのは当然です。「取りこぼし」は分散格納の証拠そのものです。
④ ロングポーリング — 「全サーバー」を照会して空応答を減らす
- 公式:「Long polling ... queries all servers for messages」「Reduce false empty responses by querying all—rather than a subset of—Amazon SQS servers.」
- 「The maximum long polling wait time is 20 seconds.」
- 2つの空応答を区別する:empty response(本当に無い)と false empty response(有るのにサブセットに入らず返らなかった)。ロングポーリングは後者を大幅に減らす。
- ただし公式は「稀に、特にWaitTimeSecondsを小さくした場合、メッセージが残っていても空応答が返ることがある」とも注記しており、ゼロになる保証ではない。
ショートポーリングが「サブセットしか見ない」ことの裏返しで、ロングポーリングは「全サーバーを見る+少し待つ」ことで空応答(特に false empty response)を減らします。③と④を並べると、ポーリング設計そのものが「メッセージは複数サーバーに分散している」という前提の上に立っていることが読み取れます。これはLambda編のイベントソースマッピングでポーラーがSQSを叩くとき、内部で起きていることそのものです(既習のポーリングvsプッシュの、ポーリング側の内部)。
⑤ キューは一時保管庫 — 保持期間とサイズ上限という「境界」
- 保持:「By default, a message is retained for 4 days. The minimum is 60 seconds (1 minute). The maximum is 1,209,600 seconds (14 days).」
- サイズ:「The minimum message size is 1 byte (1 character). The maximum is 1,048,576 bytes (1 MiB).」— 2025年8月に旧256KiBから1MiBに引き上げ済み(AWS What's New「Amazon SQS increases maximum message payload size to 1 MiB」)。古い教材の「256KB」は現在は誤り。
- 1MiB超は Amazon SQS Extended Client Library(Java/Python)で本体をS3に格納し参照を送る。最大ペイロード2GB。同期クライアントのみ対応。
SQSは永続ストアではなく一時保管庫です。保持期間(既定4日)は「取り出されなければいつか消える」という有効期限であり、サイズ上限(1MiB)は「本文の運搬役であって巨大データの倉庫ではない」という設計思想の表れです。大きなペイロードはS3に置いて参照だけ流す——S3編で見た「オブジェクトストアに本体、キューにはポインタ」という役割分担がそのまま当てはまります。