この記事は ハンズラボ 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へ反映(非同期)
(2)についてですが、スタンダードキュー内で注文データの順序が守られていないのではないかという懸念がありました。このDynamoDBの注文レコードは上書きされる仕様となっていたため、順序を誤ると古いデータが最新の状態として画面に表示されることになっていました。
以前は注文データは画像上部のスタンダードキューを通っていましたが、今回画像下部のFIFOキューを追加し、問題のあった注文データのみFIFOキューを通るように変更しました。FIFOであれば、キューへ送った順に取り出されるので注文データが順番を誤まる心配がなくなるというわけです。
次節以降ではFIFO特有の設定とについて少し書きます。
FIFO特有の設定
FIFO Queueの作成自体は設定を気にしなければ数秒で終わりますが、導入する際は最低でもメッセージ重複排除IDと、メッセージグループIDについては少し考慮した方が良さそうです。
メッセージ重複排除ID
適宜、公式より説明を拝借します。
とAWS公式に書いてありますが、この説明は私にはわかりづらく、もう少し読むと
とのことです。要するに、「同一の重複排除IDが設定されたメッセージをキューへ送っても5分間の間は受付けられない」ということのようです。
ちなみに、重複排除IDの設定についてですが、二通り方法があります。
(1) FIFO作成時に設定
(2) sendMessage時にDeduplicateIdを指定
(1)の方が楽だったので、以下のようにFIFO作成時に設定しました。
メッセージグループID
AWS公式より
との事です。こちらも少し分かりづらいですが、「グループ内の順序は厳密に守られるが、他のグループのメッセージとは順番が前後する場合がある」と理解しました。
今回はキューに入れた順に取り出されれば良かったので、特にグループは気にせず、以下のようにMessageGroupIdには定値を入れました。
1 2 3 4 5 |
$sqs->sendMessage([ 'QueueUrl' => 'https://.../queue.fifo', 'MessageBody' => $body, 'MessageGroupId' => 'group', ]); |
移行後談
移行後、半年ほど経ち、その間ハンズメッセというセールも経験しましたが、問題報告はありません。あとは、TokyoリージョンにFIFOがリリースされれば、そちらに移ろうかという所です。
明日は14日目のsho-hitomiさんです。