AWSの話題を中心に、日々の業務やプログラミングの徒然を綴るエンジニアブログです。

HANDS LAB

HANDS LAB ENGINEERS BLOG

ハンズラボエンジニアブログ

カテゴリー: SQS

Standard Queue から FIFO Queue へ移行した話


この記事は ハンズラボ Advent Calendar 2017 13日目の記事です。
こんにちは、最近、社会人1年目が過ぎた村上です。

今回システム的な問題を解決すべく、ECサイトハンズネットの裏側で動いているSQS(Simple Queue Service)のスタンダードキューの一部をFIFOキューへ移行した話を書きたいと思います。
Tokyoリージョンは2017年上旬予定と聞いたのですが、AWSコンソールを見てみると2017/12/15現在、未だリリースされていないようです。オレゴン、オハイオ、バージニア北部、EU(Ireland) のリージョンは利用できます。
細かい説明はAWS公式に任せて、スタンダードキューとFIFOキューの主な違い、移行の経緯やFIFO特有の設定についてお話しできればと思います。

 

スタンダードキューとFIFOキューの主な違い

 
まずは簡単にスタンダードキューとFIFOキューの違いについて触れます。

上記表にあるように順番についてはスタンダードはベストエフォートとあり、まれに順番を守れない事があります。「大量の画像データをある形式に従って変換する」といった処理の順番を気にしない用途には向いていると思います。しかし、今回の改修対象についてですが、順番を誤ってはいけない場所で使われています。詳しくは次節で。

また、メッセージの配信回数なのですが、スタンダードキューはまれに同じメッセージが複数回配信されることがあるので注意が必要です。

 

なぜFIFOに移行したのか

 

ユーザからの不具合報告

一般的なECサイト同様、ハンズネットで注文した後に、注文済みの商品の数量変更やキャンセルができます。それらの操作が注文履歴画面に反映されないという不具合がユーザから報告される事が定期的にあったため調査しました。その結果、SQSのスタンダードキューを使ったデータ連携が怪しく、部分的にFIFOキューへ移行することにしました。

スダンダードキューは順番を守れないことがある

このシステムの注文データの反映方法は2通りあります(なぜ、二通りあるのかは一口では語れないです 汗)。

(1) 注文後、リアルタイムでDynamoDBを更新
(2) テキスト形式のデータが、SQSのスタンダードキューを通ってDynamoDBへ反映(非同期)

[改修後イメージ、スタンダード、FIFOが共存]

 

(2)についてですが、スタンダードキュー内で注文データの順序が守られていないのではないかという懸念がありました。このDynamoDBの注文レコードは上書きされる仕様となっていたため、順序を誤ると古いデータが最新の状態として画面に表示されることになっていました。
以前は注文データは画像上部のスタンダードキューを通っていましたが、今回画像下部のFIFOキューを追加し、問題のあった注文データのみFIFOキューを通るように変更しました。FIFOであれば、キューへ送った順に取り出されるので注文データが順番を誤まる心配がなくなるというわけです。

次節以降ではFIFO特有の設定とについて少し書きます。

【補足】 ハンズネットがユニケージ開発手法で開発され、そこから移行しようとしている(Bash→PHP, ファイル→DB)という特殊な事情もあり、少し複雑なシステムとなっています。いずれは上記の(2)のテキスト形式レコードをDynamoへ反映する処理は無くしたいと考えています。

 

FIFO特有の設定

 
FIFO Queueの作成自体は設定を気にしなければ数秒で終わりますが、導入する際は最低でもメッセージ重複排除IDと、メッセージグループIDについては少し考慮した方が良さそうです。

メッセージ重複排除ID

適宜、公式より説明を拝借します。

メッセージ重複排除ID: 送信されたメッセージの重複排除に使用するトークン。特定のメッセージ重複排除 ID を持つメッセージが正常に送信された場合、同じメッセージ重複排除 ID を持つ送信メッセージは正常に受け付けられますが、5 分間の重複排除間隔の間は配信されません。

 
とAWS公式に書いてありますが、この説明は私にはわかりづらく、もう少し読むと

スタンダード キューとは異なり、FIFO キューでは重複メッセージがありません。FIFO キューを使用すると、重複をキューに送信することを防止できます。5 分間の重複排除間隔内に SendMessage アクションを再試行しても、Amazon SQS ではキューに重複を挿入しません

 
とのことです。要するに、「同一の重複排除IDが設定されたメッセージをキューへ送っても5分間の間は受付けられない」ということのようです。

ちなみに、重複排除IDの設定についてですが、二通り方法があります。
(1) FIFO作成時に設定
(2) sendMessage時にDeduplicateIdを指定

(1)の方が楽だったので、以下のようにFIFO作成時に設定しました。

メッセージグループID

AWS公式より

メッセージグループID: 特定のメッセージグループに属するメッセージを指定するタグ。同じメッセージグループに属するメッセージは、メッセージグループに相対的な厳密な順序で、常に 1 つずつ処理されます (ただし、別のメッセージグループに属するメッセージは、入れ替わって処理される場合があります)。

 
との事です。こちらも少し分かりづらいですが、「グループ内の順序は厳密に守られるが、他のグループのメッセージとは順番が前後する場合がある」と理解しました。
今回はキューに入れた順に取り出されれば良かったので、特にグループは気にせず、以下のようにMessageGroupIdには定値を入れました。

移行後談

 
移行後、半年ほど経ち、その間ハンズメッセというセールも経験しましたが、問題報告はありません。あとは、TokyoリージョンにFIFOがリリースされれば、そちらに移ろうかという所です。

明日は14日目のsho-hitomiさんです。