MicroAd Developers Blog

マイクロアドのエンジニアブログです。インフラ、開発、分析について発信していきます。

【新卒エンジニア向け】マイクロアドエンジニアの技術スタック(バッチ開発ユニット編)

こんにちは!
システム開発部BDU(BigData Development Unit)でアプリケーションエンジニアをしている高橋です。

主にマイクロアドが気になっている社外のエンジニアの方やマイクロアドの新入社員の方向けに、自分たちのユニットが使っている技術について共有します。 メインは大規模データを取り扱うバッチ開発の話になるので、広告配信に興味のある方は以下の記事をご覧ください。
developers.microad.co.jp

BDU(以降「バッチ開発ユニット」と呼ぶ)では主にETL/ELT1処理のバッチを開発しています。 広告配信ログやアクセスログなどのデータを元にして、適切な形に加工した上で各データストアへと蓄積します。

ログの流れの詳細については以下の記事をご覧ください。
developers.microad.co.jp

大規模データを取り扱うバッチ開発に関連する技術への興味がある方にとって、この記事が少しでも参考になれば幸いです。

プログラミング言語

主なプログラミング言語はPythonです。
Pythonを採用している理由として以下が挙げられます。

  • シンプルな言語仕様で可読性の高い実装がしやすい(メンテナンス性も高い)
  • 機械学習でも使われることが多いので、他ユニットと知見の共有ができる

可読性という観点では、バッチ開発ユニットに途中合流した自分でもロジックを追いやすくメンテナンスしやすい実装になっていると感じます。 後述する設計も相まって、内定者アルバイトの子からも「バッチの実装が良く練られていて開発しやすいです!」とのお声をいただきました。

知見の共有という観点でも、機械学習ユニットと同じような処理を行う場合にお互いの実装を参考にできるので恩恵があります。

ワークフローエンジン

ワークフローエンジン2にはDigdagを使用しています。
Digdagはワークフローの記述をYAMLライクに書けるほか、session_timeというジョブの実行予定時間を保持する概念のおかげで、後からでも過去分のデータを再集計しやすい設計になっています。 バッチは失敗した場合に運用作業が発生しがちなので、このsession_timeには大いに助けられています。

Digdagを採用した経緯については以下の記事をご覧ください。
developers.microad.co.jp

設計

バッチの設計自体もシンプルでPythonっぽいコードを目指しています。 Digdag以外のワークフローエンジンに換装されても対応しやすいように、ワークフロー側にはロジックを持たせないようにしています。

バッチ設計の詳細については以下の記事をご覧ください。
developers.microad.co.jp

データ基盤

現行基盤

ETL処理はHadoopエコシステム(Hive、HDFSなど)を中心に構成されています。
PythonからHiveのクエリを流して値を集計し、機械学習や広告配信の請求等に使用するテーブルを準備します。 Python自身で直接ファイルを処理する機会も少なからずありますが、大規模データ処理はほぼHadoopに寄せています。

Hadoopエコシステムについては以下の記事が参考になります。
developers.microad.co.jp

今後の展望

現在、新しいデータ基盤への移管を予定しています。
新しいデータ基盤では、オンプレミス上のPySpark on Kubernetesを用いてS3互換ストレージ上のデータを処理する想定で準備を進めています。
今まで集計ロジックはHiveクエリで実装していましたが、PySparkを使用することによりPythonコード上でpandasライクにデータを処理できそうです。

PySpark移行の詳細については以下の記事をご覧ください。
developers.microad.co.jp

CI/CD

継続的インテグレーション(CI)3、継続的デリバリー(CD)4ツールとしてはJenkinsを、GitリポジトリにはGitHub Enterpriseを利用しています。
git pushをトリガーに、自動で単体テストの実行とコンフリクトのチェックがなされます。 単体テスト実行時にはyapf、flake8、mypyといったフォーマッター/リンターのチェックも同時に行われます。 チェックを通過し変更を反映したブランチからマスターブランチにマージされる際、Jenkinsから自動でリリースされるような仕組みになっています。

保守・運用

技術スタックからは少しそれた話になってしまいますが、バッチ開発ユニットではエラー時の運用作業が度々発生します。 エラーにすぐ気が付けるように、メーリングリスト宛に送信されたエラーメールをSlack通知する形を取っています。 送信失敗頻度が限りなく低いメールの堅牢さとSlackの手軽さを合わせた仕組みで、非常に運用しやすいです。
エラーではないものの処理が遅延している場合にもSlack通知されます。

Slack通知の詳細については以下の記事をご覧ください。
developers.microad.co.jp

ミドルウェア

Docker

Digdagで実行されるバッチは全てDockerコンテナ上で実行されます。
コンテナの使用により、物理サーバの環境を気にせずバッチが実装できるのは大きなメリットです。 サーバ上の環境を汚すこともありません。
そのほかHiveクエリの自動テストにも活用しています。

Hiveクエリの自動テストの詳細については以下の記事をご覧ください。
developers.microad.co.jp

MySQL

広告配信や運用画面で使用される設定情報等はRDBMSのMySQLに格納されています。
それに伴ってバッチがMySQL上のテーブルを更新することもあれば、ログ集計時に必要な情報を参照することもあります。 Hadoop上でログを集計する時にMySQLの情報が必要になる場合は、スナップショットをHadoop上に転送して使用します。

Redis

Redisは高速で動作するキーバリューストア5です。
読み書きのパフォーマンスが求められる広告配信で使用されています。 バッチからRedisの情報を読み込んだり、逆に書き込んだりする場合があります。

Kafka

Kafkaはメッセージキューイング6システムの一種で、分散処理により大規模なデータが扱えます。
広告配信ログ等がKafkaにキューイングされ、後続のフローで順次処理されていきます。 Kafkaに記録されたJSONをバッチから読み込んだり、逆に書き込んだりする場合があります。

Kafkaを含めたデータ基盤の詳細については以下の記事をご覧ください。
developers.microad.co.jp

まとめ

以下、バッチ開発ユニットで使っている技術をまとめました!
一部クラウドで処理しているものもありますが、基本的にはオンプレミスです。

  • 言語
    • Python (PySpark含む)
    • SQL(MySQL, HiveQL)
    • Java
  • データベース等
    • Hadoopエコシステム(Hive, Impala, HDFS)
    • MySQL
    • Redis
    • BigQuery
    • Amazon S3
    • Google Cloud Storage
  • ミドルウェア・ライブラリ等
    • Docker, Kubernetes, Rancher
    • Kafka
    • Flume
  • CI/CD・監視ツール等
    • Jenkins
    • Grafana
    • Cacti
  • バージョン管理
    • Git

終わりに

ここまで読んでいただきありがとうございました。 今回各項目でリンクした技術ブログには詳細が記述されているので、ぜひご覧ください。

マイクロアドでは「大規模データを取り扱いたい!」「Pythonを使って開発したい!」というエンジニアを積極的に募集しています。興味を持った方は是非こちらからご応募下さい!

recruit.microad.co.jp


  1. いずれもExtract, Transform, Loadの頭文字をフローにしたがって並べたもので、データを利用しやすい形へと変換する一連の処理。
  2. 一連の処理プロセスを制御し、自動で実行してくれるソフトウェア。
  3. 変更を反映したコードが共有リポジトリにマージされる際、ビルドとテストが自動実行される仕組み。
  4. CIを延長し、変更を反映したコードのリリース作業を自動化する仕組み。
  5. 一意のキー(Key)に対して保存したい値(Value)を格納するデータベース。
  6. 異なるシステム間でメッセージを一時的に保持し、非同期的にデータを送受信するための方法。