ソーシャルゲームの運用に欠かせないデータ分析基盤の作り方

はじめに

初めまして、バックエンドエンジニアの伊藤皓程です。2015年にサイバーエージェントに入社してからソーシャルゲーム2本、その後アドテクで広告配信システムの開発に携わりました。以前のプロジェクトではデイリーで数TBのログを収集と分析を行なっていた経験があり、また個人でAWS AthenaのTypeScript・Node.js用のクライアントライブラリ1を公開しています。今回は今年にリリースしたアプリボットの新データ分析基盤についてご紹介したいと思います。

経緯

アプリボットではゲームの運用の改善のためにユーザの行動ログの分析に力をいれており、Redshiftを利用したデータ分析基盤2がありました。一方でゲームの運用年数や運用タイトルの増加などにより以下のような課題がありました。

  • Redshiftのストレージ容量の枯渇
  • デイリーのレポート集計バッチの実行時間の増加
  • データ分析基盤の運用コストの増加・人材不足

RedshiftはAWSが提供しているデータウェアハウスで、PostgreSQL Likeなインターフェースでアプリエンジニアでも馴染みやすく、クラスターのノードを増減させることでスケールアウトができ、挿入されたデータが自動で列指向で保存されるためビッグデータの分析に適したサービスだと思います。一方で上記の課題にあげたようにストレージに制限があるため、例えばストレージが不足した場合ノードを追加する必要があります。(年間数百万単位のコスト3が増加します…)
またログの追加や仕様の変更などによるテーブルのマイグレーションや、定期的なバキューム、パフォーマンスを低下させる要因となる重いクエリの検知や停止などなど運用コストがかかります。
その他にも、ETLに使用していたFlyDataというサービスが終了するなどの要因があり、2018年12月から全ての運用タイトルを新データ分析基盤に移行することになりました。

データ分析基盤

思想

新データ分析基盤ではデータレイク4という思想を取り入れています。ユーザの行動ログ、情報、サービスのマスターデータなど様々なデータを一旦全てS3に配置し、分析などで利用する場合はそれぞれのデータに適したサービス(Hadoop, Presto, Apache Sparkなど)でアクセスし、分析結果を再びS3に再配置します。このようにデータのストレージとデータを分析するサービスを分離して結合を疎にすることで以下のようなメリットが考えられます。

  • ストレージが枯渇しない
  • 利用用途に適したデータフォーマットに変換できる
  • 新しい分析サービスへの移行がデータウェアハウスに比べて容易

データレイクではS3にデータを集約するため、ストレージの容量を気にすることなくデータを保存することが可能です。またS3のライフサイクルを活用することで、アクセス頻度に応じたコスト管理が可能です。また行動ログはユーザからのお問い合わせの調査などでも活用しますが、調査で実行するクエリと集計で実行するクエリは大きく異なっています。用途に合わせて適したデータフォーマット(csv, json, parquet)で保存することで、パフォーマンスや料金コストを最適化し調査や分析の業務の効率化が可能です。また今後もデータ分析のサービスは次々と登場するはずなので、より良いサービスへ移行しようとした場合もデータレイクのほうが容易に移行することができると思います。
余談にはなりますが、新データ分析基盤はDiveという名で開発しています。この名前は「データの湖に潜って宝を発掘する」という思いからつけられています。

システムアーキテクチャ

以下のようなシステムアーキテクチャの概要となっています。
cb9ffef5-7e74-5fe8-157e-1fb4f763fd02

マネージドサービスを積極的を利用しサーバレスなアーキテクチャにすることでサーバのインスタンスなどの管理など運用コストを軽減しつつ、システムの全体の可用性が向上するように設計しました。
アーキテクチャを大きく分類すると「データの集約」、「データの加工」、「データの可視化」に分けることができます。以下でそれぞれについてもう少し詳細にご紹介します。

データの集約

ログ

ログをS3に送信する方法として以下の3つの方法があります。
1. 各サーバでデイリーで前日分のログをローテートしてS3に送信する
2. 各サーバで出力されたログを直接S3に送信する
3. 集約サーバ(Aggregator)を作って各サーバから集約サーバに送信し、集約サーバからS3に送信する

1の方法はオートスケールなどを行わないシステムではもっともログの送信時にログがロストするリスクが低いという長所がありますが、当日分のログで分析や調査を行うことは難しくなります。2の方法は3に比べるとログが消失するリスクが低いです。しかし各サーバがそれぞれファイルをS3に配置するため、ファイルが細切れになってしまい利用する際に不便です。またファイルを大きくしようとするとより長時間バッファする必要があるため、障害などが発生した時にログが消失するリスクが上がってしまいます。
Diveでは3の方法を採用していてKinesis Data StreamsとKinesis Data Firehoseを利用してアプリケーション(APIサーバなど)から出力されたユーザのシステムログやユーザの行動ログなどを集約してS3に送信しています。以前はEC2などのインスタンスを集約サーバ(Aggregator)として利用していましたが、ログの転送量のスパイクやインスタンスのディスクの使用率、CPU使用率、ネットワークの帯域など気にすることが多かったです。
上記の2つのサービスを利用することで堅牢なログの集約処理をより容易に行うことが可能です。またtd-agentのfluent-plugin-kinesisを利用してKPL5を行うことでKinesis Data Streamのリソースを効率的に利用できます。
ただしKinesis Data Firehoseが送信したS3のオブジェクトのKeyは[prefix]/YYYY/MM/DD/HH/[name]になっていますが、これをAthenaのテーブルのパーティションとして利用する場合以下の2つ考慮すべき点があります。まずKeyの日付はUTCになっているためパーティションを指定する場合はJSTに変換が必要になることがあります。またkeyの時間はログが出力された時間とずれる場合があります。これを考慮せずにパーティションを指定したクエリを実行すると誤った結果が返却されます。
上記の利用から以下のような共通の項目を定義し、S3にオブジェクトが配置されたイベントをトリガーにLambdaが起動してをdatetimeからログを再配置しています。DiveではKinesis Data FirehoseからS3に送信されたログをStream Log, Lambdaによって再配置されたログをRaw Logと定義しています。

{
"enviroment": "prd",
"project": "hoge",
"table": "gacha",
"version": 1,
"datetime": ""2019-05-10T11:19:24Z",
"log": { ... }
}

マスターデータ

API GatewayとLambdaを利用し各プロジェクトのMaster DataをDiveと同期するAPIを提供しています。同期されたマスターデータはデータの加工や可視化時に利用されます。

データの管理・加工

ETL

AWSのマネージドサービスだけをとってもデータのETLが可能なサービスは様々あります。
1. Glue Job
2. EMR
3. Athena
1はApache Sparkを利用したETLが可能で、S3だけでなく、RedshiftやMySQLなど様々なデータソースを統合することが可能で、クラスターなどの管理が不要なETLに特化したマネージドサービスです。その一方で料金は比較的高くなります。
2に関してはApache Spark以外のHadoopで動作する分散処理フレームワークを動作させることが可能でより柔軟な環境を構築することが可能ですが、クラスターの管理などのコストがかかります。
DiveではAWS BatchがデイリーでAthenaに対してCTAS6を実行してRaw LogのETL、Parquet(列指向)への変換を行いS3にSummary Dataとして再配置しています。
746b82d8-290b-552e-6b61-068e04f57b62

Athenaを選択した主な理由は以下の3つです。

  • SQLでETLを行えるため、学習コストが低い
  • フルマネージドサービスなためリソースの管理などが不要
  • デイリーのログが数十GB程度

ただしデータレイク思考なアーキテクチャになっているため、分析サービスの変更などが比較的容易なため、今後ETLの要件やチームの規模によっては別のものを活用したりすることもあるかもしれません。

データカタログ

S3のSummary DataMaster Dataに対応するデータカタログGlueのCrawlerを利用してS3のデータから自動で管理しています。一方でRaw Logに関しては、行動ログに対応するデータカタログの追加や修正などをログの出力元のアプリケーションのリリースより先に行う(データの更新よりも先にデータカタログを更新したい)ためDDLを利用して手動で管理しています。DDLに関してはyamlで書かれた行動ログの定義の中間ファイルから自動生成していて、このyamlから行動ログの仕様書などのドキュメントも生成しています。
データカタログをDDLで手動で管理する場合、テーブル名にスキーマのバージョンのサフィックスをつけ、そのテーブルを参照するビューを作成することをお勧めします。

create or replace view user_gift as
select * from user_gift_v2

Athenaは現在テーブルのカラムの追加や変更などのDDL(ALTER文)には対応していないため、テーブルのスキーマを変更するには一度テーブルをDROPして、CREATEし直す必要があります。(DROPしてもS3のデータが消えることはありません)またパーティショニングを行なっている場合、テーブルをCREATEしてもパーティションを追加し直すまではデータをSELECTをすることが出来ません。そのためスキーマを変更するには数分程度、テーブルが利用できない時間が発生してしまいます。上記のようなビューを作りそれを使用するようなルールを作ることで、以下のようにダウンタイム無しでスキーマを変更することが可能です。

  1. 次のバージョンのサフィックスのテーブルをCREATE
  2. 1のテーブルにパーティションを追加
  3. ビューの向き先を次の1のテーブルに変更
  4. 前のバージョンのテーブルをDROP

Athenaのパフォーマンスチューニング

Athenaのパフォーマンスを向上7させるためにDiveで行なっていることをご紹介します。
1. Raw Logは日付と時間、Summary Dataは日付でパーティションを分割
2. Raw LogのS3のオブジェクトを適切なサイズに結合
3. Summary Dataはparquetにファイルのフォーマットを変換、snappyに圧縮
4. クエリの見直し

Raw LogはFirehoseでログを集約してS3に保存していますが、それでも1日で数百オブジェクトに分かれてしまいます。パーティショニングをしているため、数日程度のパーティションでは十分に高速ですが、パーティションの範囲を広くするとAthenaがS3からデータをスキャンする時間がかかりクエリのパフォーマンスがかなり低下し、場合によっては「Too many open files…」などのAthenaのエラーが発生します。またAthenaではエラーが発生していなくてもS3の拡張メトリクス8の5xxErrorsが頻発していることがあります。もし単純なクエリでもAthenaの実行時間が長い場合は一度上記のメトリックスを確認してみることをお勧めします。
Diveではバッチで1ファイル最大で1GB程度にオブジェクトを結合するようにしたところ、クエリの実行時間が平均75%程度削減できました。(ただしあくまで高速化されるのはデータスキャンのみなので、クエリによって効果は変わります。)

またSummary Dataは列指向のフォーマットに変換していますが、Raw Logはあえて行指向のJSONまたはCSVを使用しています。Raw Logはユーザのお問い合わせの調査などの用途で使用される場合がほとんどですが、この場合以下のようなシンプルなクエリが実行されることが多いです。

select * from user_gift where ymd = '2019-02-01' and user_id = 1234

ログから複数行のレコードのカラムをすべて取ってくる場合、parquetに変換されていてもデータスキャン量は変わらずクエリの実行時間も行指向のフォーマットに比べて増加する場合があり、一概に列指向のほうが適切という訳ではありません9

データの可視化

Diveではデータの可視化のためにTableauとRe:dashを導入しています。Tableauは主にソーシャルゲームの詳細KPIや広告効果の分析と可視化、Re:dashはお問い合わせ調査や主要KPIのリアルタイムでの可視化などで使用されています。
以前はエンジニア以外の人がお問い合わせ調査をするために各運用タイトルで管理画面に調査用のGUIを作っていましたが、Re:dashを導入してからはクエリを登録するだけで簡単に調査用の画面を作成できるようになりました。
faec1b7d-1644-fee8-d054-518f439a116e

Re:dashの活用事例は別の記事で詳しくご紹介しているのでこちらもご参照ください。
ソーシャルゲームの価値を上げるログデータのつくりかた

まとめ

アプリボットでは2019年にDiveという内製のデータ分析基盤への移行が完了しました。Diveではデータレイクの思想を取り入れ、Kinesis, S3, Athena, Glue, Batch, Lambda, SQSなど様々なマネージドサービスを組み合わせ、可用性が高く、柔軟なシステムアーキテクチャが実現できました。
また以前は全てのデイリーの集計に4~5時間かかっていましたが、Athenaのクエリのチューニングや保存されたデータのファイルフォーマットやサイズを最適化することで20分程度で完了するようになりました。さらにデータ分析基盤の費用は以前に比べて1/4程度になりました。
ソーシャルゲームは一見アドテクなどのサービスと比較するとログなどのデータ量は少ないですが、ゲームの仕様やユーザの状態は複雑でノイズなども多く、またゲームのジャンルによっても見るべき指標が異なってくるためデータ分析を活用する難易度は高いです。今後はデータ分析基盤の運用を通じで、分散処理や統計手法などの技術やノウハウをさらに蓄積して、ソーシャルゲームの運用へさらに活用出来るようにしていきたいと思っています。
今回は基盤の大まかな概要についてお話ししましたが、今後はさらにクエリのチューニングや採用している技術の詳細など深掘りしてご紹介出来ればと思います。

参考