SQSでのインシデント
はじめに
何が起きたか
決済の処理システムで二重請求のインシデントが発生しました。原因調査と対応に追われました。
システム構成は AWS SQS FIFO + Lambda という一般的なものでしたが、Lambda のタイムアウトをきっかけに、可視性タイムアウト後のメッセージ再配信により二重処理が発生しました。
この記事で学べること
- SQS の At-least-once Delivery が実際にどう動作するか
- Lambda タイムアウトと SQS 可視性タイムアウトの関係
- FIFO キューでも重複が起きる理由
- 冪等性の重要性と実装アプローチ
対象読者
- SQS + Lambda で非同期処理を実装している方
- 分散システムでの重複処理に悩んでいる方
- 冪等性の実装を検討している方
インシデントの全容
システム構成
主要な設定:
- Lambda Timeout: 30秒
- SQS 可視性タイムアウト: 10分
- Batch Size: 10件
- Message Group ID: 全メッセージで同一値
タイムライン(図解)
技術的な原因分析
なぜタイムアウトで二重処理が起きるのか
Lambda がタイムアウトすると、以下のフローで二重処理が発生します:
SQS の At-least-once Delivery
AWS は、SQS が「最低1回配信」を保証する仕組みであることを明確に説明しています。
AWS 公式ドキュメントより:
"Amazon SQS stores copies of your messages on multiple servers for redundancy and high availability. On rare occasions, one of the servers that stores a copy of a message might be unavailable when you receive or delete a message. If this occurs, the copy of the message isn't deleted on the server that is unavailable, and you might get that message copy again when you receive messages. Design your applications to be idempotent (they should not be affected adversely when processing the same message more than once)."
出典: Amazon SQS at-least-once delivery
重要なポイント:
- SQS は高可用性のためメッセージを複数サーバーに保存
- サーバー障害時に削除されないコピーが残る可能性がある
-
アプリケーション側で冪等性を実装する必要がある
可視性タイムアウトの仕組み:
AWS 公式ドキュメントより:
"The visibility timeout starts as soon as a message is delivered to you. During this period, you're expected to process and delete the message. If you don't delete it before the timeout expires, the message becomes visible again in the queue and can be retrieved by another consumer."
出典: Amazon SQS visibility timeout
今回のケース:
- 可視性タイムアウト: 10分
- Lambda タイムアウト: 30秒
- Lambda が30秒でタイムアウト → メッセージ削除されず
- 10分後にメッセージが再び見える → 再配信
FIFO でも起きる理由
FIFO キューは "Exactly-once processing" を提供すると説明されていますが、これには重要な前提条件があります。
AWS 公式ドキュメントより:
"Unlike standard queues, FIFO queues don't introduce duplicate messages. FIFO queues help you avoid sending duplicates to a queue. If you retry the SendMessage action within the 5-minute deduplication interval, Amazon SQS doesn't introduce any duplicates into the queue."
出典: Exactly-once processing in Amazon SQS
FIFO が保証すること:
- 送信時の重複排除(5分間のdeduplication window内)
- 順序保証
- メッセージグループID内での厳密な順序
FIFO が保証しないこと:
- Consumer(Lambda)での処理失敗時の重複防止
- タイムアウト後の再配信防止
AWS FAQ より:
"FIFO queues are designed to never introduce duplicate messages. However, your message producer might introduce duplicates in certain scenarios: for example, if the producer sends a message, does not receive a response, and then resends the same message."
出典: Amazon SQS FAQs
今回のケースでは:
- FIFO の重複排除機能は正常に動作していた(送信時)
- しかし、Lambda タイムアウトによる再配信は防げない
- FIFO でも Consumer 側での冪等性実装が必須
解決策
冪等性を実装しよう
AWS 公式が繰り返し強調しているように、分散システムにおいて冪等性の実装は必須です。
これは FIFO キューでも同様に重要です。
まとめ
重要なポイント
-
SQS は At-least-once delivery が前提
- 標準キューも FIFO キューも、Consumer 側での処理失敗時の重複は防げない
-
FIFO の "Exactly-once" の正確な理解
- 送信時の重複排除(5分間)のみ保証
- Consumer 側での冪等性は別途必要
-
Lambda タイムアウトと可視性タイムアウトの関係
- Lambda タイムアウト < 可視性タイムアウト の場合、メッセージの再配信が発生する
- 冪等性の実装で二重処理を防ぐ
Discussion