コネヒト開発者ブログ

コネヒト開発者ブログ

Firebase AnalyticsからBigQueryへの日次データ同期が突如不規則になった事象に対応した話

こんにちは。インフラエンジニアの永井(shnagai)です。

今回は、Firebase AnalyticsからBigQueryへの日次データ同期処理の時間が大幅にずれた際に取った対策について書こうと思います。

内容はざっくり下記3点です。

  • 背景説明
  • Firebase AnalyticsからBigQueryへのデータ同期
  • 解決策

背景説明

コネヒトでは、家族ノートという「ママリ」内の検索データとQ&Aデータを可視化したデータ分析サービスを運営しています。

info-kazokunote.mamari.jp

家族ノート内で使っている検索データは、FirebaseAnalyticsを使ってトラッキングしている行動ログをベースにしています。

サービス性質上FirebaseAnalyticsの行動ログは大切で、元のデータがうまく出来ていないとデータの欠損等にも繋がってしまいます。

※もちろんそう簡単に欠損を出すわけにはいかないので、後続の集計処理のスケジュールを工夫したりしてデータ欠損が出ない取り組みはしていますが。

Firebase AnalyticsからBigQueryへのデータ同期

データ同期のフロー

今回の事象の説明に入る前に、FirebaseAnalyticsからBigQueryへのデータ同期のフローをざっくり書くと下記のようになっています。

デバイス
↓ ①行動ログを送信
FirebaseAnalytics
↓ ②リアルタイムにデータ同期
BigQuery(events_intraday_yyyymmdd)
↓ ③日次テーブルとして書き出し
BigQuery(events_yyyymmdd)

ちなみにFirebaseAnalytics上の設定は下記のキャプチャのように「毎日」「ストリーミング」同期の両方をオンにしています

今回課題になった点

※再掲

デバイス
↓ ①行動ログを送信
FirebaseAnalytics
↓ ②リアルタイムにデータ同期
BigQuery(events_intraday_yyyymmdd)
↓ ③日次テーブルとして書き出し
BigQuery(events_yyyymmdd)

家族ノートでは、③の日次テーブルを起点に集計データを作って最終的に表示するBigQueryのビューを作成しています。

ただ、③の日次テーブルの書き出し時間は不定期で、BigQueryの events_yyyymmdd テーブルが何時に出来るのかは利用者側ではハンドリング出来ません。

これまでの経験則から、ある程度この時間までにはデータが出来ているというバッファをもったタイミングで後続の集計処理をスケジュールベースで動かしていました。

そんな中、今年の6月1日のタイミングから時間のズレが大きくなり、元のスケジュールではカバーできない状況が発生しました。(これまでの時間帯に日次テーブルが出来る日もあれば大幅にタイミングが遅れる日も散見され始めました)

具体的に言うと、集計テーブルに対するデータのテストでアラートが出る日が増えてきており何かしらの対応が必要になりました。

解決策

解決策は簡単で、集計テーブルの対象を③ events_yyyymmdd のみから、③events_yyyymmdd or ② events_intraday_yyyymmddという形に変えました。

events_intraday テーブルの仕様がよくわからず、結果としてデータ重複等予期せぬことが起きるのは怖かったので、1ヶ月ほど併行して出来上がるデータに差分がないかをチェックしました。

結果、うまく動いた日は同じ数のイベントがあり、旧来の処理がコケた日も新処理ではデータがうまく出来ていることが確認出来たので正式に新方式に切り替えることにしました。

これまでのクエリ:

FROM
    `hogehoge.analytics_99999999.events_*`
WHERE (_TABLE_SUFFIX = FORMAT_DATE("%Y%m%d", DATE_SUB(@run_date, INTERVAL 1 DAY))

新方式のクエリ:

FROM
    `hogehoge.analytics_99999999.events_*`
WHERE (_TABLE_SUFFIX = FORMAT_DATE("%Y%m%d", DATE_SUB(@run_date, INTERVAL 1 DAY))
      OR _TABLE_SUFFIX = CONCAT('intraday_', FORMAT_DATE("%Y%m%d", DATE_SUB(@run_date, INTERVAL 1 DAY))))

どうしようか困っていた時に、下記ツイートのアイデアに非常に助けられました。

この場でお礼を伝えさせていただきます!ありがとうございます。

今回はニッチなネタでしたが、このブログを読んでたまたま同じ悩みに遭遇している誰かの救いになれば幸いです。