blog

DeNAのエンジニアが考えていることや、担当しているサービスについて情報発信しています

2019.10.17 DeNAインフラノウハウ発信プロジェクト

アプリログを BigQuery に入れるまで

by Takahiro Kida

#infrastructure #cost-optimization #cloud-migration #paas #saas #analysis-infrastructure #infra-quality

こんにちは、IT基盤部の貴田です。

DeNA では分析環境の BigQuery 移行を進めています。
先の記事では、移行の背景や、 MySQL のデータを Embulk を用いて BigQuery に入れる工程を紹介しました。
今回は、ウェブアプリケーションが出力したログを定常的に BigQuery に入れて活用するフローについて書きます。

文中の料金については、すべて 2019年10月時点の 東京リージョンのものです。

大まかな流れ

  1. アプリがログを吐く
  2. サーバー内の daemon がログを処理し、適切な Cloud Storage Bucket にアップロードする
  3. Cloud Storage から BigQuery に import する

というシンプルな構成ですが、設計するにあたりいくつか考慮した点があるので、順に説明します。 概略図中に、 1 ~ 4 の数字を振っている部分です。

(1) どうして直接 BigQuery にデータを送信せず、 Cloud Storage に格納するのか?

web server から bq load や ストリーミング挿入 を用いて直接 BigQuery にデータを集めることも検討しましたが、コストと安定性を考え、まずは Cloud Storage にデータを格納し、必要なものを必要なタイミングでだけ BigQuery にエクスポートする構成としました。

コスト

1GB・1ヶ月あたりの料金はこのようになっており、 めったに使わないデータは Coldline Storage に置くことでストレージコストを下げられます。

サービス料金
Cloud Storage (Standard Storage)$0.023
Cloud Storage (Coldline Storage)$0.006
BigQuery$0.023

また、 BigQuery のストレージ料金は非圧縮の状態のデータサイズが課金対象となります。
Cloud Storage 上に gzip で圧縮した状態で保持することで、ストレージ料金を大きく下げることができます。

Cloud Storage から BigQuery にエクスポートする際に料金が少しかかりますが、それについては後述します。

安定性

BigQuery のテーブルは型を持っているため、何かしらのバグでログに不正な文字列が入ると、 BigQuery へのインサートは失敗します。その場合にログを web server 内部に溜めてしまうと web server のディスク領域が逼迫したり、本番稼働しているサーバーに入っての復旧作業が必要となったりするデメリットがあります。

まずはどんなデータでも受け入れてくれる Cloud Storage にデータを入れてしまい、その後起きうる問題と web server を切り離す意味でも、まずは Cloud Storage にデータを入れる構成が優位です。

(2) gcs daemon の役割

分析用のアプリログはもともと hdfs に格納することを前提に出力していたため、各行が下記フォーマットになっています。

 ${hdfs上のpath情報}\t${その他メタ情報...}\t${データ本体(JSON または LTSV)}

また、 DeNA の web app は多くの場合、分析用のアプリログを単一のファイルに書き出し続けています。

そのため、

  • hdfs上のpath情報 を Cloud Storage Bucket 名・path への変換を行う
  • ログファイルを一定時間ごと・bucket/pathごとに分割する
  • BigQuery に直接 export できるファイル形式(json.gz) に変換する

という処理を行っています。

(3) BigQuery へのデータ取り込み vs 外部データソースの活用

Cloud Storage に格納されたデータを活用する場合、2通りの方法があります。

DeNAでは前者の BigQuery にエクスポートする方法を採用しました。

ドキュメントに記載があるとおり、後者の方法を用いると、 BigQuery の機能が一部制限されてしまいます。

なかでも、

  • テーブルのパーティショニングがサポートされない
  • クエリの実行結果がキャッシュされない

という制限は致命的で、大規模なデータを扱った場合にクエリ料金が跳ね上がる恐れがあります。

一方、前者の方法でエクスポートする場合、それ自体にほとんど料金が発生しません。
Cloud Storage (Standard Storage) と BigQuery が同リージョンにある場合、エクスポートで発生する料金は下記のもののみです。

  • Cloud Storage の get api 料金 10,000ファイルあたり $0.004
  • BigQuery ストレージ料金 1ヶ月・1Gb あたり $0.023
    • 時間単位での課金なので、利用後すぐに消せば費用が非常に小さくなる

このとおり、 Cloud Storage -> BigQuery へのエクスポートは非常に安価に行うことができます。
エクスポートすれば BigQuery の機能をフルに活用できるため、大規模なデータ分析において外部データソースの機能を使うシーンはほぼ無いと思います。

(4) 型自動判定の夢…

Cloud Storage 上の JSON を BigQuery にエクスポートする際、すべてのカラムの型を明示的に指定しています。
利用者にあらかじめスプレッドシートにカラム名と型を記載してもらうことで実現しています。

BigQuery へのデータ読み込みでは、型の自動判定機能があり( CLI でいうところの –autodetect オプション )、当初はこちらの活用を考えていました。

実際、ほとんどのケースでは自動判定はうまく働きます。
しかし、極稀にエラーが起きてしまうケースがありました。
例えば、ほとんどの行は version: "3.0" と記載されており、実数値として判定されるが、新しく version: "3.0.1" がリリースされるとこれは実数に変換できないのでエラーになる、というケースです。

BigQuery には一部のカラムだけの型を指定してデータを取り込む機能がないため、利用者に全ての型をあらかじめ入力してもらう UX となってしまいました。

BigQuery は型を意識した分析用だと割り切る必要がありそうです。

まとめ

今回の設計を通して得られた知見をまとめます。

  • BigQuery にデータを直接入れるのではなく、 Cloud Storage をデータレイクとして活用することで、安価でかつ安定する
  • Web server 上で BigQuery に読み込ませられる形式に変換・圧縮して Cloud Storage に配置することで、後続の処理をシンプルにできる
  • BigQuery の外部データソース機能は使わず、 Cloud Storage から都度 export するほうがよい
  • BigQuery を使う以上、型を意識した設計にすべき。 型自動判定は万能でなく、アドホックな処理のみに利用する

最後に

hadoop を用いた分析基盤から BigQuery を用いた分析基盤に移行するにあたり、とくに迷った部分・試行錯誤の結果当初の方針を変更した点などを紹介させていただきました。
何かしらの参考になれば幸いです。

最後まで読んでいただき、ありがとうございます!
この記事をシェアしていただける方はこちらからお願いします。

recruit

DeNAでは、失敗を恐れず常に挑戦し続けるエンジニアを募集しています。