こんにちは、MA基盤チームの田島です。私達のチームではMAIL、LINE、PUSH通知といったユーザへの配信をしています。その中でもマス・セグメント配信という一斉に行う配信では、配信対象者のセグメント抽出にBigQueryを利用しています。また、配信前に必要なデータをBigQueryに連携しデータマートの集計をしたり、配信後には配信実績の登録などの更新処理をしています。
そのような処理を定期的に行っているため、ネットワークの問題やサーバーの不調などにより処理が途中で失敗することがあります。そこで、リトライを容易にするため、すべての処理を冪等にしました。今回その中でも、BigQueryの追記処理に絞ってどのように冪等化したのかについて紹介します。
マス・セグメント配信基盤の紹介
まず、各配信の流れを簡易化したものが以下になります。
上記の流れはDigdagというワークフローエンジンを利用することで実現しています。 Digdagの基盤については、以下のテックブログをご参照ください。
課題
バッチ処理においては、ネットワークの問題やサーバーの不調により予期せぬタイミングで処理が異常終了することもあります。発生時にはDigdagのリトライ機能を利用し、処理単位ごとに自動リトライしています。しかし、なにも考えずにリトライするとデータが重複して登録されたり、同じ配信を複数回行ってしまうといった問題が起こり得ます。
BigQueryの更新処理については、最近導入されたTransactionの仕組みがあります。この機能を使うことで一連のクエリをTransactionの中で完結できます。しかし、クエリの更新処理がすべて完了しCommitの完了後、アプリケーションやDigdagで異常が発生することもあります。そのときリトライすると同じトランザクション処理を再度実行してしまい、同じ処理が重複して実行されてしまいます。
このような事象はかなりレアケースではありますが、安定したバッチ処理をするにはこの問題に関しても対応する必要があります。
冪等化
上記の課題を解決するためにデータの更新処理を含め、すべての処理を冪等化しました。それにより、処理が失敗した場合はただリトライをするだけで整合性が担保されるようにしました。そして、リトライは自動的に行われているので、手動でのオペレーションも不要です。
BigQuery追記処理に関する冪等化の取り組み
ここからはBigQueryのデータ処理に限定して、冪等化の取り組みについて紹介していきます。今回扱う更新処理は追記処理に限定しています。
冪等にならないケース
BigQueryの追記処理において冪等にならないようなケースについてのパターンを紹介します。今回紹介するケースの他に、自己参照したデータを利用するUPDATE文も冪等にならないことがあります。しかし、私達のシステムではBigQueryにおいてそのような処理を行っていないため、今回は省略し追記処理に限定しました。
INSERT
最初はINSERT文です。BigQueryはユニークキー制約が無いため、INSERT処理は常に追記されることになります。よって、INSERT成功後に処理が失敗しリトライされてしまうとデータの重複が発生します。
PUSH通知の実績テーブルである push_delivered テーブルへのINSERT処理を例に、リトライによりデータが重複するケースを紹介します。
初期データ
まず初期データとして以下の2レコードが存在するとします。
続きはこちら