• Home
  • コーポレートブログ Geniee’s BLOG
コーポレートブログ

Geniee’s BLOG

ジーニーは最先端の広告テクノロジーで
顧客の収益を最大化します。

こんにちは。広報の真鍋です。
昨夜、オンライン動画学習サービス「Schoo(スクー)」にて、弊社プロダクト企画グループマネージャーの川﨑が先生を務めるSSP講座が生放送されました。
今回は、その裏側をご紹介します。

20時少し前。都内某所にある、Schooさんのスタジオに到着。
ご挨拶を済ませ、早速スタジオ内で番組ディレクターさんから本番の流れについてご説明を受けます。
今回の番組では、受講生代表としてフリーアナウンサーの花海さん(写真左)が、川﨑(右)と掛け合いをしながら進行してくださいます。受講生の立場に立って、どこで質問を挟むとより理解が深まるか、伝わりやすいか、事前にすり合わせます。

本番45分前。いよいよリハーサルです。
オープニングからカメラテストを兼ねて、本番さながらにトークが繰り広げられています。「ここは、カメラ目線で受講生に語り掛ける感じで。」といった指示をいただきつつ、順調に進んでいきます。

Schooさんでは、ITスキルやビジネススキル、プログラミング、Webデザインなど、仕事で使える幅広い授業を、オンライン上で受講生参加型かつ生放送されています。
昨今、テクノロジーの進化とともに、益々関心の高まっているデジタルマーケティング領域について、基礎から学べる講座を開講されるとのことで、その中のSSP講座をジーニーが担当させていただきました。

ジーニーは、ご存知の方も多いかと思いますが、2011年4月からGenieeSSPの提供を開始し、今では国内最大規模にまで拡大しています。GenieeSSPは、国内の媒体社様のみならず、「SoftBank Ads Platform」を始めとする提携先サービスへのOEM提供や、アジア諸国の企業様にも幅広くご提供しています。

補足説明はこのくらいにして、そろそろ本番。
初めての生放送ということで、さぞや川﨑は緊張していることだろうと思いきや、全くそんな様子はなく、花海さんに、SSPについて熱く解説していました。

そして本番。受講生が次々とオンライン(着席という表示が出る)になっていき、21時に番組がスタートしました。

今回の講座では、“SSPって聞いたことはあるけど、よく理解できていない”という方を対象に、Web広告の歴史を振り返りながら、アドテクノロジーとは?SSPとは?といった基本的な内容をお話させていただきました。また、これからのSSPのあり方については、GenieeSSPのプロダクト企画を担当する川﨑ならではの、想いのこもった解説となりました。

見逃した方は、こちらからアーカイブで閲覧できるそうですので、是非ご覧になってください。

放送終了後、スタジオの壁にかけられたメッセージボードへ。ITベンチャーの社長様をはじめ、個性豊かな出演者の方々のサインで埋め尽くされています。
空きスペースを見つけて、川﨑も。ジーニーのロゴマーク(魔人のマーク)と一緒に書かせていただきました。

生放送をご覧くださった皆さま、Schooの皆さま、ありがとうございました!
川﨑さん、お疲れ様でした!

☆★☆★☆★

川﨑をはじめ、プロダクトに熱い想いを持つジーニーやジーニーメンバーにご興味をお持ちいただけた方は、是非こちら
川﨑のプロフィール・インタビューはこちら

 

こんにちは、人事の見並です。
ジーニーは、社員の35%がエンジニアで、SSPやDSP、マーケティングオートメーションといったプロダクトを全て独自開発しています。
今回は、そんなジーニーの心臓部とも言える開発現場の日常ををお届けします。

執務エリアの全体感はこんな様子です。間仕切りなどなく、オープンでフラットなフロアでエンジニアリングに皆さん勤しんでいます。
写真の中でプカプカ浮いている風船は、ここ半年くらいで入られた方々の名前が書かれています。(こちらは、入社歓迎の気持ちを込めて、1つひとつ人事が準備しています)
新卒・中途ともに、続々とジョインされているのが風船からもわかります。

それでは早速、最近どんなシステム開発を進めているのかレポートします!

まずはGenieeSSPの島から

まずは、ジーニーの基幹プロダクトであるGenieeSSPを開発している島へやってまいりました。
GenieeSSPは、様々なオンラインメディアやアプリへ広告を配信し、そのマネタイズをサポートするプロダクトです。多くのトラフィックを捌くバックエンド側と、メディアの方々に提供するWEBシステム側とに大別されます。

当たり前ですが、私が入社した頃(4年前)と比べると、大きくシステム環境が変わっています。使っている言語のバージョンアップ準備が進んでいたり、提供するものも、WEBシステム、広告配信のバックエンド、アプリ向けのSDKと多岐に渡り、業務を通してエンジニアリングの幅が広げられそうな環境となっていました。

開発言語やミドルウェアなど、「こんなのも使っているんですか?」と色々聞いていたら、あれやこれやと周りのエンジニアの方々が回答してくれて、和気藹々とした雰囲気でした。集中していたところお邪魔いたしました。

続いてGenieeDSPの島へ

次は、GenieeDSPを開発している島へやってまいりました。
GenieeDSPは、GenieeSSPが扱う広告枠を中心に、届けたいユーザーをターゲティングし、広告を配信するプロダクトです。
こちらも多くのリクエストを受け付けて広告を配信するバックエンド側と、広告主の方々に提供するWEBシステム側とに大別されます。

GenieeDSPは、私が入社した後、2014年3月にできたプロダクトです。当時は今よりずっと少ない人数のエンジニアで、とても泥臭く立ち上げが行われていました。
今では、GenieeSSPに続く収益柱へと成長してきており、昔を思うと本当に作り上げてきたエンジニアの方々に拍手です。
また、WEBシステム側はサーバサイドの開発言語をPHPからJavaに移行し、UI/UXの改善も社内で進行していて、ますますこれからが楽しみなプロダクトです。

最後はMAJINの島へ

最後は、ジーニーで最も新しいプロダクトであるマーケティングオートメーションツールのMAJINを開発している島へやってまいりました。
MAJINは、集客施策から販促活動、顧客管理までを一気通貫で担い、データもひと繋ぎに活用してマーケティング活動に必要な機能をオールインワンで提供しています。
新機能の開発スピードも非常に早く、LINE連携機能の追加や、機械学習を用いた新機能の研究開発も進んでいます。

これまで取り組んできたアドテクノロジーからマーケティングテクノロジーへ拡張した、新たなプロダクトということもあり、使っている技術環境も毛色が異なります。
モダンな技術を使いながらも、私達の基幹事業であるアドテクノロジー分野とのデータ連携もしっかりと図っています。
生まれてまだ1年の若いプロダクトですが、こちらもUI/UXをブラッシュアップしたり、目に見えない基盤部分もガンガン改善していっています。
最近は、エンジニア発信で気づいたら機能が追加されていたり、改善がなされていたりと、自社内の出来事ながらビックリすることがあります。

お客様へ提供しているプロダクト開発部門以外に、事業サイドやコーポレートサイドとプロダクトを繋ぐ経営情報システム開発の部門や、プロダクトへ横断的に関わるアーキテクチャやインフラを担う基盤技術開発の部門などがあり、みんなで一丸となって事業の成長を支えています。

その他、執務エリアの隣にはこんなスペースも設けています。

休憩エリアです。ちょっと気分を変えて開発をしたり、コーヒーを飲みながら息抜きをしたりしています。

研究開発の一環としてVRエリアも!私は生まれて初めてここでVRを体験しましたが、なかなか衝撃的でした。

よりリアルな開発現場を感じていただけるよう、先月からエンジニアブログを開始しています。

GENIEEエンジニアブログ

是非こちらも見てみてください!

いかがでしたか?
もっと具体的な開発言語や使っているツールなども知りたいと思った方、ジーニーの開発にご興味のわいた方は、是非こちらから!

ジーニー採用サイト

弊社へ遊びにきていただけましたら、ざっくばらんにお話しできますので、是非気軽にいらしてください!

Date
Author
社風やジーニーでの働き方などをご紹介していきます。 ジーニー人事チーム

こんにちは。広報の真鍋です。
ジーニーが独自開発したマーケティングオートメーションツール「MAJIN」では、定期的に企業のマーケティングご担当者様をお招きしたセミナーを開催しています。
今回は、7月27日に株式会社フリーセル様と共同で開催したセミナー『マーケティングオートメーション(MA)×動画というマーケティング“力”』についてご紹介します。

暑い中、セミナー会場は満員御礼!

ここ数年、スマートフォン上などで動画広告を目にする機会が増えていると思います。動画広告市場は右肩上がりの成長を続けていて、2020年には2017年の倍の市場規模になると言われています。

そんな注目度の高い動画と、マーケティングオートメーションを組み合わせるとどんなことができるのか、どんな効果が得られるのか。
今回のセミナーでは、フリーセル社のマーケティングエキスパートである河島美津雄氏と、ジーニー・MA事業本部の細山が、具体的な施策事例を含め、講演させていただきました。

株式会社フリーセル マーケティングソリューション本部 マーケティング戦略課 エキスパート 河島美津雄氏

セミナーの第1部『マーケティング戦術としての動画という選択肢』では、フリーセル社河島氏より、動画を活用することでどのようなマーケティング課題が解決されるかが具体例を交えながら解説されたほか、より効果が上がる動画制作の基本や活用メリットについて説明されました。
また、第2部『伝わる“動画”を“MA”で伝えていく方法』では、当社細山よりMA×動画の利用例を挙げながら、動画を使った顧客アプローチ方法などについて解説させていただきました。

MA事業本部 細山紳二

登壇を終えた細山は、
「参加者の皆様のお話を伺って、動画とMAの活用を本格的に考えていらっしゃる企業様が非常に多いということを改めて感じました。セミナー終了後の交流会では、自社のビジネスモデルに置き換えた場合、どのように動画を活用できるのか?といった、より深いご質問をされるご参加者もいて、始まりから終わりまで密度の濃い会でした。」
と話していました。

マーケティングオートメーションツールは、海外製から国内製まで、多機能・高価格なツールから機能を絞った低価格のツールまで、幅広く提供されています。このため、実際に運用に携わる企業のマーケティング担当者様は、自社に合ったツールはどれなのか、どんな機能をどう使えば効果的なのか、迷われることも多いかと思います。

ジーニーの「MAJIN」は、そんな利用者の方々の声を反映し、ちょうど1年前に後発で開発・提供開始されました。「MAJIN」では、今後も利用者の方々からいただく声を参考にしながら、実務担当者の方々に役立つセミナーを開催していく予定です。

 

<最後にちょっと宣伝です!>
次回のセミナーは、株式会社船井総研ITソリューションズとの共催です!
テーマ「MA×インサイドセールス」8/9(水)14時~
ご興味のある方は、是非ご参加ください。詳しくはこちら。

 

★☆★☆★☆★☆★☆★☆

ジーニーでは、マーケティング担当者のお悩みを解決し新たな価値を創造すべく、積極的に機能開発やサービス提供に取り組んでいます。そんなジーニーで一緒に世界を変えていきませんか?興味のある方は、こちら!

 

こんにちは。R&D本部・経営情報システム部の友安です。

経営情報システム部では社内システム・プロダクト横断でのお金周りの開発や監査対応、
社内のコミュニケーション効率化など、多岐にわたり社内の問題解決に努めています。

社内の権限管理

組織が大きくなってくると色々と統制が求められるようになります。 統制の1つに権限管理の強化が挙げられます。 しかし管理の強化には運用コストが伴います。そのため、より小さな運用コストで実現することは重要なテーマになります。

今回は商用版MySQLの権限管理に便利なPAM認証プラグインの機能を紹介します。

MySQL×LDAP認証

やりたかったこと

  • 運用時やリリース時に利用していた共用のMySQLユーザを廃止し、DB上の権限をメンバーごとに管理する。
  • それを低い運用コストで実現したい。
  • 弊社はサーバへのアクセス権限などをLDAP*1で管理していたので、MySQL上の権限もLDAPで一元的に管理したかった。

MySQL PAM認証プラグイン

商用版MySQLの機能にPAM認証プラグインがあります。

PAM認証プラグインを用いると、MySQLログイン時の認証をLDAPに委譲し、更にLDAPのグループとMySQLユーザのマッピングを指定できます。

これにより、LDAPのdb_adminというグループに所属するエントリがMySQLログインした際は、強力な権限を持つMySQLユーザになる、といったことができます。

既にLDAPを運用している組織では、多重管理による運用コスト増大を回避しつつMySQL上の権限を制御出来ます。

設定例

想定するLDAPのグループとマッピング先のMySQLユーザに付与したい権限は以下とします。
今回の例ではシンプルな3グループで設定します。

LDAPグループ所属メンバーDB上の権限MySQLユーザ
db_adminDBAALLdb_admine_user
operation運用チームデータ更新operation_user
engineer全エンジニアreadonlyengineer_user

pam設定ファイルの作成

以下の形式でPAM認証プラグインが使用するpam設定ファイルを作成します。

----------------------------------------------------------------
#%PAM-1.0
auth required {認証モジュール}
account required {認証モジュール}
----------------------------------------------------------------

使用するLDAPクライアントはpbis-openです。

/etc/pam.d以下にpam設定ファイルを作成します。ファイル名はmysqlとします。

/etc/pam.d/MySQL

----------------------------------------------------------------
#%PAM-1.0
auth required pam_lsass.so
account required pam_lsass.so
----------------------------------------------------------------

MySQL側の設定

  • PAM認証プラグインをインストール
----------------------------------------------------------------
install plugin authentication_pam soname 'authentication_pam.so';

----------------------------------------------------------------
  • MySQLユーザを作成、権限設定
----------------------------------------------------------------
-- プロキシされるユーザの作成
CREATE USER 'db_admin_user'@'192.168.%.%' IDENTIFIED BY 'hoge1';
CREATE USER 'operation_user'@'192.168.%.%' IDENTIFIED BY 'hoge2';
CREATE USER 'engineer_user'@'192.168.%.%' IDENTIFIED BY 'hoge3';

-- 各ユーザに権限付与
GRANT ALL ON *.* TO 'db_admin_user'@'192.168.%.%';
GRANT SELECT,UPDATE,INSERT,DELETE ON *.* TO 'operation_user'@'192.168.%.%';
GRANT SELECT ON *.* TO 'engineer_user'@'192.168.%.%';

-- プロキシ用の匿名ユーザを作成
-- AS以降の文字列(authentiation_string)は {pam設定ファイル名}, {LDAPグループ}={MySQLユーザ} の形式で記述する 
CREATE USER ''@'192.168.%.%' IDENTIFIED WITH authentication_pam AS 'mysql, db_admin=db_admin_user, operation=operation_user, engineer=engineer_user';

-- プロキシ権限を付与
GRANT PROXY ON 'db_admin_user'@'192.168.%.%' TO ''@'192.168.%.%';
GRANT PROXY ON 'operation_user'@'192.168.%.%' TO ''@'192.168.%.%';
GRANT PROXY ON 'engineer_user'@'192.168.%.%' TO ''@'192.168.%.%';
----------------------------------------------------------------

ここまでの設定で、LDAPのユーザ名でログイン時に次のような流れで認証されるようになります。

  1. ユーザ名をLDAPユーザにしてログイン。
  2. mysql.userテーブル上に合致するユーザ名が見つからない。
  3. 合致するユーザ名が無い場合、匿名ユーザにマッチングされる。
  4. 匿名ユーザの認証にPAM認証プラグインが設定されているため、PAM認証が行われる。
  5. 認証に成功すると、匿名ユーザはLDAPグループごとにマッピングしたMySQLユーザをプロキシする。

上記のLDAPグループに複数所属している場合、記述した順でマッピングされる。

例だと db_admin > operation > engineerの優先度でマップされるので、 db_adminとengineerに所属するユーザはdb_admin_userとなる

ログイン動作確認

  • ログイン
----------------------------------------------------------------
mysql -u {ldap_user} -p
----------------------------------------------------------------
  • ログイン後
----------------------------------------------------------------
SELECT user(),current_user();
----------------------------------------------------------------

上記のクエリ実行でuser()にLDAPのユーザ名が、current_user()にLDAPグループに対応したMySQLユーザ名が表示されます。

踏み台ホストで権限を変える

MySQLサーバにアクセスする踏み台ホストを変えることで、マッピングするユーザを変えることもできます。

これにより、192.168.0.1からのアクセス時はreadonlyなユーザにマッピングし、SELECTして調査したいだけの時は、不要な権限を持たないMySQLユーザを使ってもらうといった運用も可能です。

192.168.0.1からアクセスした際はreadonlyなユーザにマッピングするように設定

----------------------------------------------------------------
CREATE USER 'engineer_readonly'@'192.168.0.1' IDENTIFIED BY 'hogehoge';
GRANT SELECT ON *.* TO 'engineer_readonly'@'192.168.0.1';
-- エンジニア全員が所属するengineerグループにengineer_readonlyユーザをマッピング。これにより192.168.0.1からアクセスした際は全エンジニアがreadonly権限のユーザになる
CREATE USER ''@'192.168.0.1' IDENTIFIED WITH authentication_pam AS 'mysql, engineer=engineer_readonly';
GRANT PROXY ON 'engineer_readonly'@'bar' TO ''@'192.168.0.1';
----------------------------------------------------------------

監査ログ

MySQLの監査ログプラグイン(こちらも商用版MySQL)と組み合わせると、?LDAPグループとマッピングされるMySQLユーザを指定したフィルタを作ることで、簡単にLDAP認証でログインした全ユーザをロギング対象にすることができます。*2

----------------------------------------------------------------

注意

MySQL 5.7.12以前のバージョンでは監査ログプラグインの挙動にバグがあり、LDAP認証でログインした全てのユーザをロギング対象にするには、 全LDAPエントリ×アクセス元となり得る全てのhostを指定するフィルタを作成しなければいけません。*3

----------------------------------------------------------------

まとめ

商用版MySQLの機能であるPAM認証プラグインを利用し、ログイン認証をLDAPに委譲することで、 低運用コストでのデータベース権限管理を実現する方法を紹介しました。

特にLDAPを運用している組織にとって有用な方法になり得ます。
実運用ではリリーススピードを緩めないような権限委譲など、組織の設計が重要になると思います。

*1:ネットワーク機器やユーザーなどの情報を管理するディレクトリサービスへ接続するためのプロトコルhttp://www.atmarkit.co.jp/aig/06network/ldap.html

*2:MySQL :: MySQL 5.7 Reference Manual :: 6.4.5 MySQL Enterprise Audit

*3:18 Changes in MySQL 5.7.12 (2016-04-11, General Availability)

Date
Author
エンジニアの視点から、様々な技術、サービス開発秘話、イベントをご紹介していきます。 ジーニーエンジニアチーム

仕事をしている中で、日々立ちはだかるさまざまな壁。ジーニーでは、「Over the Border」を2017年度のスローガンとし、そんな壁をみなで乗り越えるため結束しています。

今回は、インターンを入口に、新卒第一世代として入社した、ジーニー歴5年目の井上雅尭にインタビュー。今年の3月には、短期のインドネシア駐在も経験したバイタリティあふれる井上は、どのようにして仕事の壁を乗り越えてきたのでしょうか。

入社の経緯とこれまで携わってきた仕事をおしえてください。

私は就職活動というものが苦手でした。さっぱりうまくいかず、どうやって社会に出ようかと考えた結果、自分でやるしかないというアイデアが浮かびました。とりあえず修行だなと思い、「IT産業」「急成長ベンチャー」を条件にインターンシップ先を探していたところ、友人にジーニーを教えてもらったことがきっかけで知りました。本当に偶然です(笑)。

インターン時代は、アタックリストを作り、電話を掛ける営業活動を半年ほど経験。そのまま2013年に入社することになり、営業、商品企画、R&Dを経て、今に至ります。

 

これまでで印象に残っている仕事は?

商品企画が3年以上で一番長く、その中でも、今では部にまで発展したベンダーの立ち上げがハイライトでしょうか。廣瀬さん(現:取締役)や篠塚さん(現:CTO)とともに、プロダクトが完成していない状態で営業先に提案し、納品までに辻棲を合わせるというリーン(笑)なサイクルを回しながら、売り方やフローを固めてセールスに実装していきました。ただ、その頃、導入を決めた事業者は、今でもお付き合いのあるところが多いですね。

現在は経営企画室で海外案件を担当されていますが、最近乗り越えた一番大きな壁は?

インドネシア現地法人の社長と一緒に立ち上げた営業チームが、2017年5月度の単月予算を設立後初めて達成することができたことでしょうか。

グループ会社のデマンド事業改善で、 2月末から1ヵ月現地に駐在してきました。英語も全然できないし、これまでやってきたサプライサイドとは真逆の領域でかなり不安でした。準備期間も2週間ないような状況でしたが、 「楽しそう」だったので、社長には二つ返事で「行きます!」と返事しました。

現地人だけのオフィスに一人で派遣され、最初の1週間は何を言われてもわからず、ほぼ無価値な存在でした。無価値なりに営業に同行し、英語でサマリーを聞き徐々に状況を把握していきました。

 

そんな中、インドネシアで心がけていたことは?

「小さなギブをする」 「現地化する」です。君は誰?という状況下では何かしらの価値を示し、存在を認めてもらう必要があります。

大型案件の消化に苦戦し、GTI(Geniee Technology Indonesia)の協力を得る必要が生じていました。私が間に立つことでGTIの日本人スタッフと円滑なコミュニケーションがとれ、大型案件の消化が進み、手始めのギブができました。

また、当時一人しかいなかった営業マンが、私の派遣と同時期に一気に6人に増えたのですが、まだセールスマネジメントの仕組みがありませんでした。その仕組みづくりは経験があったので、ヨミ表(受注計画表)とヒアリングシートをオンラインで作成し、彼らに営業管理の仕方をレクチャーしました。リアルタイムに管理できる仕組みはとても喜ばれました。さらに、営業マンに業界知識や商品知識が足りないことは明白だったので、勉強会を実施。5時間に及ぶこともありました。

一方、よそ者であるディスアドバンテージを払拭するには可能な限り現地化して彼らの文化へのリスペクトを示す必要があります。毎日昼食を共にして、覚えたての現地語でウケをとっていました。「Kamu cantik.(※ 1)」は便利です。ちなみに、昼食は濁った川のほとりにある掘っ立て小屋のようなところで一食100円の食事(笑)。これがなかなか「Enak(※2)」です。

※1…君は美しい ※2…美味しい

社内の若手メンバーヘアドバイスを

正直に言って、越えられなかった壁もたくさんあります。たくさんの失敗を経て、自分は何をすべきで、何をすべきでないのかの判断精度があがってきた気がします。そもそも全ての壁を超える必要などないと考えているので、余計な壁はスルーします(笑)。これ大事。新卒の方には、全ての壁を超える必要などない、ということを伝えたい一方で、その判断材料や経験値をためる意味でも、まずは与えられた仕事を全力でやってみるといいと思います。例え失敗しても「できないことがわかった」というポジティブな経験になります。

ジーニーは厳しいようで、実は優しい会社です。本当です。与えられた仕事に全力で挑みつつ「やってみたい」、「楽しそう」という気持ちが動くようなチャンスに飛びついたり、自ら生み出したりして仕事を楽しんで欲しいです。

 

* * *

 

ジーニーでは、アジアNo.1を目指し、海外展開にも力を入れています。こんなジーニーで一緒に「Over the Border」していきながら、会社も自分も成長させていきませんか? 興味をお持ちいただけた方は、ぜひこちらからコンタクトしてください。バイタリティあふれる皆さんからのご応募お待ちしています!

ジーニーの心臓部隊!エンジニアたちによる、エンジニアブログを本日スタートしました!

GENIEEエンジニアブログ → こちら

初回は、CTO×編集長対談です。ぜひご覧ください。

* * *

GENIEEエンジニアブログ編集長を務めることになりました、R&D本部マーケティングオートメーション開発部の張です。ジーニーへは、2016年4月に入社して、主にフロントエンドを担当しています。初回ということで、CTOの篠塚とブログを始めるきっかけや、ジーニーの開発部門の紹介をさせていただきます。

 (写真左:CTO・篠塚 英伸、右:エンジニアブログ編集長・張 志鋒)

ブログを始めるワケ

張:
ジーニーは、結構、面白い技術を使っていて、色々発信したいと思っていたんです。でも、ブログもなく、あまり社外に伝える機会がないな、と思っていました。
篠塚(CTO):
そうですね。R&D本部全体では、「誇れるものをつくろう」といつも言っているので、「誇れるものをつくったら、自慢しなきゃ!」と。それを発信していきたいというのが、このブログを始めた1つのきっかけですね。
あと、自分で勉強して、プロダクト開発に反映させて、「よかったね」と。それはそれで良いんですけど、エンジニアのキャリアやスキルアップを考えると、社内外の場でお互いに共有したり、発信したりしていくのも大事。そこでいろんな人からフィードバックを得て、ブラッシュアップしていく方が成長できると思うんですよ。
張:
このブログを通して、優秀なエンジニアの方たちにジーニーの技術を知ってもらいたいし、それによって、友を呼びたいですね。
篠塚:
ジーニーは、あまり中のことを語らない人たちが多いけれど、アドテク自体がマニアックなので、おもしろい内容が書けるんじゃないかと思うんです。アドテクノロジーやマーケティングテクノロジーについて、興味を持ってくれるエンジニアが増えたらいいなと。そして、仲間が増えたら嬉しいですね。

ジーニーのエンジニアリング部門

篠塚:
R&D本部には、「アド・プラットフォーム開発部」「マーケティングオートメーション開発部」「基盤技術開発部」「経営情報システム開発部」の4つの部があり、それぞれ25人・15人・10人・10人で合計60人ぐらいいます。
張:
メンバーのバックグラウンドは、コンピュータサイエンス系が多いですが、文系の人もいれば、美大(アート)出身者もいて、面白い人が集まっています。ちなみに僕は経済学部でした。
篠塚:
張さん、文系だったんだ!びっくり。
新卒も8割くらいはコンピュータサイエンス出身ですね。理工系も少しいます。
張:
中途では、1/3ぐらいがアドテク出身で、SI出身も多いですね。あとは、ゲーム系とか、Webサービス系とか、いろんなバックグラウンドの人がいると思います。
篠塚:
総じて、尖っている人が多い気がしますね。みんなそれぞれ特長的。
あと、女性は現状2名しかいません!
張:
特にアドテク業界は、女性が少ないんですかね?!
篠塚:
アドテク女子って、本当に少ない(笑)
張:
ジーニーは、女性も働きやすい環境ではあると思うんですけど。
篠塚:
男性も育休取っていますし。エンジニアではないですが、女性社員で産休育休をとって復帰している前例もあります。女性の感性がもっとプロダクトに入ると、いいと思うんですよね。

仕事の仕方や雰囲気

張:
僕は、何でも屋ですね。以前は、フロントエンドとバックエンドが分かれていましたが、最近は、一緒に仕事をするようになってきています。タスクに対して、みんなで力を合わせてやるフルスタックというイメージです。
篠塚:
そうですね、インフラは分かれていますが、フルスタックを目指しています。
もちろん、人によって得意領域はあるけれど、他の人の業務を知らないと、最適な設計ができないと思います。
これまで規模が小さい頃は、とにかくスピード重視で役割を分けてやってきました。しかし、規模も大きくなり、今後、ジーニープラットフォームとして連携していくことを考えると、技術的な切り分けではなく、タスクの解決方法に合わせて分担していく方がいいと考えています。そのためには、エンジニア1人ひとりが広範囲のことを知らなければいけないですね。
張:
もちろん初めから全部できる、というのは難しいですが、例えば、データベースは何を使っているかとか、どういう構成で何を処理しているかなど、プロダクトを知らないと、フロントでもアプリケーションでもモノづくりはできません。お互いを知らないと、チームとして動けないんですよね。
篠塚:
この体制は、特長的かもしれませんね。
張:
最近は、チームを越えてお互いを知るようになってきたと思います。もっともっと、壁をなくしていきたいですね。そのための1つの方法として、週1回社内勉強会をやっています。こちらのチームでは新技術を使って開発しているのに、隣のチームはよくわからない、というのではもったいないですから。プログラミング業界でよく言われるような“車輪の再発明”とかしたくないからね。知識が共有できれば、ジーニーの開発パワーはもっと上がってくると思うんです。
篠塚:
勉強会のほかには、月に一度、R&Dの全体会があります。メンバー持ち回りでLTをやっているんですけど、わりと面白いですよ。飲み会とかより、ずっと盛り上がるんです。この前のLTでは、あるメンバーが「モテたいから髪色を変えたい」ということで、似合う色を判定するためだけの仕組みをわざわざAI使って作ってみましたって発表がありました。みんな大爆笑でしたよ。「変えればいいじゃん!」って。そんな雰囲気の部門です(笑)

ジーニーならではのこと

篠塚:
普段よく目に触れるWebサービスは、UIを提供するのが一般的ですが、アドテクやマーケティングオートメーションでは、見える部分がほとんどありません。表には出ませんが、例えば、潜在顧客に1通メールを出したり、1つバナー広告が表示されたりするまでには、いろいろなドラマがあるんですよ!データを集めて、次も出すべきかどうかというスコアリングや分析をして、良かったのか悪かったのか、その結果をフィードバックする仕組みは、顧客のマーケティング施策全体や業績に大きく関わってきます。目に見える部分はほんのわずかですが、裏側ではけっこう壮大なことをやっているんですよ。
張:
MAJIN(マーケティングオートメーションツール)も、目に見えないところで結構頑張っているんですよ。MAJINは、フロントもバックもなかなか複雑で、データベースの開発とかにも手を出そうとしています。最先端の論文で研究して技術を実装してみたり、普通ならあまり使わない言語を使ってみたり、いろいろ試して、改善して、結果どんどん良くなっています。ジーニーの場合、実験的な試みや失敗も許容してくれる環境があるので、最先端の技術にチャレンジできるのがいいですね。
篠塚:
他社が採用していないような技術も、積極的に研究したり、実験的に採用したり、産学連携したり。いろいろやっていることを活かして、オープンソースへの貢献もしていきたいですね。
張:
新しい技術の開発は、他社だとあまり裁量権がもらえないことが多いと思うんです。僕の場合、どんどん勉強して、実際に試せるというのは、ジーニーに入って良かったことの1つだと思います。
篠塚:
営業のみんなが頑張ってくれているから、エンジニアにチャレンジできる余裕が生まれるので、ありがたいですね。いい循環が生まれていると思います。
あと、ジーニーの特徴として、データ量(トラフィック)が多いことがあります。1日のデータ処理量は、だいたい15テラくらいあるんですが、それを効率よく24時間365日動かし続けなければいけない環境って、わりと珍しいと思うんですよ。
張:
MAJINの方では、機械学習も強化していますし、AI活用も進んでくるので、そういうチャレンジをしたい方にもいい環境だと思います。

アドテクノロジーで世界を変える(=ジーニーのミッション)

篠塚:
世の中にまだ解決できてない課題があって、それを解決すると、少し世界がよくなります。なぜ、いろいろな課題が解決できないかというと、アイデアがないわけではなくて、いろいろな困難があって越えられないんですよ。
顧客の本質的な課題にしっかり応えるために、必要な技術を見極めて、ベストなものを真面目につくる。有り体のものを使うのではなく、自分たちにしかできないものを自分たちの手でつくるんです。課題自体がどんどん複雑になっているので、必然的に最先端の技術を取り入れていかなければならないわけです。そうやって、1つずつ課題を解決していくと、世の中が良くなっていくんです。それが僕たちのミッションだし、それができると「誇れるものがつくれた」ということになります。
張:
その通りです。困難があって、他の人が解決できなかったことを、僕らがエンジニアリングで解決できたら達成感がありますよね。
篠塚:
MAだったら、どこまでオートメーションにすると、本当にマーケターが楽になるかとか、人では思いつかない(できない)成果が得られるかとか。そういった壁を一つひとつ解決していくことが大事だと思っています。
張:
こんな僕たちの学びとか気づきとか、勉強会や研究について、このブログで発信していきたいと思っています。
よろしくお願いします!

* * *

今後、定期的に有用な情報を公開して参りますので、お楽しみに!

GENIEEエンジニアブログ → こちら

はじめに

こんにちは、ジーニーR&D本部アド・プラットフォーム開発部の宮下です。

今日は弊社の開発業務で普段どんなことをしているのかな、

という業務の一旦を弊社プロダクトのGenieeDSPを例にとってご紹介したいと思います。

現象

GenieeDSPは、弊社のDSP広告配信システムでSSPから来るリクエストのうち、おおむね月間800億リクエストを処理して、広告を返しています。

ある日のこと、監視システムから、配信サーバーの一台で負荷が高まっていることを示すアラートが上がってきました。

ジーニーでは各サーバーの稼働状況をモニタリングするものとして、Grafanaというツールを使用しています。

この時の状況でいうと、

  • CPU使用率は30%程度
  • load averageはほぼ限界まで高まっている(全てのCPUが処理待ち)という症状でした。

現象はリクエストの多い時間帯で起きており、症状の起きたサーバーではリクエストの処理能力が著しく落ち、ろくにリクエストを処理できない状態でした。

何かの処理がボトルネックになっていて配信サーバーのパフォーマンスが悪化しているものと思われました。

困った時はプロファイラ

ここで原因を特定すべく、Linuxのパフォーマンス解析ツールであるperfを使用しました。

perfは、関数別にCPU使用率を計測・表示してくれる便利なツールです。

ジーニーでは速度上のボトルネックになりそうな箇所を特定するためによく利用しているツールになります。(詳細は[こちら](https://perf.wiki.kernel.org/index.php/Main_Page))

早速実施してみたところ、下記のような配信サーバーの関数の各使用率が表示されました。

“`
$sudo perf top

7.55% adserver [.] backend::doPreAdSelect(geniee::lot&, std::vector<geniee::banner, std::allocator >&)
5.09% [kernel] [k] _raw_spin_lock_irq
4.06% adserver [.] geniee::util::FastIDSet::includes(int) const
3.29% adserver [.] targeting::Targeting::doIncludeTargeting(std::vector > const&, std::vector<
2.87% adserver [.] geniee::memory::zone(std::string const&)
2.40% adserver [.] std::string::find(char const*, unsigned long, unsigned long) const
“`

上記から見ると、案件のターゲティング処理をしている関数が重たそうなことがわかります。

しかしそれは今までも上位に来ていたので特に問題ではなさそうでした。

ここで一点、見慣れない関数が上位に表示されていました。

“`
5.09% [kernel] [k] _raw_spin_lock_irq
“`

また、他の現象が発言していない同スペックのサーバーを調査した結果、
`_raw_spin_lock_irq`がCPU使用率の上位に現れることはないということがわかりました。

どうやらこの関数が怪しそうです。

この関数がおそらく原因であろうという仮説のもと、より詳細に調査をすることになりました。

_raw_spin_lock_irq:ですが、これは[kernel]とperfで出力されていることからも分かるとおり、osのスケジューラ内で使用されている関数で、ある処理が、あるCPUのコアを使用している時に、他の処理からの割り込みを受けないように、変数をロックするためのものになります。

ここで、perfの機能である、その関数がどこから呼び出されてるか(callgraph)の出力をしてみます。

“`
$perf record -a — sleep 30
$perf report –stdio

|
— _raw_spin_lock_irq
|
|–49.40%–
void std::vector<geniee::banner, std::allocator >::_M_emplace_back_aux(geniee::banner&&)
| |
| |–1.55%– 0x7fd18d0a1000
| | 0x0

“`

結果、ここでわかったのは、std::vectorに要素を追加するときに呼ばれている、ということでした。

何か自分たちで作り込んだ関数が変な処理をしていてそこが特定できればなおせるのではないか?と考えていましたが、std::vectorへの要素追加は基本的な操作なので、改善の余地はあまりないように思えました。

そこで、一旦状況を整理してみました。

  • 配信サーバーはマルチスレッドかつイベントドリブンで動いている。
  • 全スレッドはカーネルにより任意のCPUを割り当てられる。
  • あるスレッドがvectorへの要素追加をしようとすると_raw_spin_lock_irqが呼ばれ、そのCPUを使おうとする別のスレッドが処理待ちになる?のではないかと思われました。

すると、

vectorへの要素追加時に他の処理がそのCPUをそもそも使わないようにすれば良い、ように思えます。

これでいくと、各スレッドが特定のCPUのみを使用するようにすると解決しそうです。

そこでtasksetコマンドを利用して、各スレッドに一つのCPUを割り当てることにしました。

tasksetコマンドは、コマンドやプログラムを特定のコアで実行することを可能にするコマンドです。(詳細は[こちら](https://linux.die.net/man/1/taskset))

“`
$taskset -c -p CPUコア番号 プロセスID
“`

というように、配信サーバーのスレッドのプロセスIDを、順々に各スレッドに対してCPUコアを割り当てていきます。

後日この現象が再発した際にサーバーにログインし、上記コマンドを実施したところ、load averageが下がり、_raw_spin_lock_irq関数がhtopの上位に来ることはほぼなくなり、なんとか事象を解決することができました。

また、この方法だとサーバーが再起動するたびに全スレッドに対してtasksetを実施しないといけないことになりそうだったので、後日配信サーバーのプログラムに1スレッドが1CPUコアを使用するように修正を行いました。

終わりに

いかがでしたでしょうか。

ジーニーでは日々増加していく膨大なリクエスト数に対して、いかにしてその処理をさばいていくのか、という課題に日夜向き合っております。

大規模なトラフィックに向き合う中で通常では遭遇しないような問題・課題もありますが、そんな時に知恵を絞って解決した時の喜びや達成感があります。

当記事でその一端をご紹介させていただきましたが、そのような課題解決に興味を持たれたり、面白そうだな、と感じていただけましたら幸いです。

ありがとうございました。

Date
Author
エンジニアの視点から、様々な技術、サービス開発秘話、イベントをご紹介していきます。 ジーニーエンジニアチーム

はじめに

どうも、R&D本部のマーケティングオートメーション開発部所属の張です。

業務では弊社のマーケティングオートメーションプラットフォーム「[MAJIN](https://ma-jin.jp/)」のフロントエンド開発・保守、基盤の改善、DevOps推進などなどに携わっています。最近仕事で主に使う言語はGoです。

初回なので、今回はMAJINのフロントエンドで使う技術を簡単に紹介いたします。

MAJINのフロントエンド

MAJINは2016年7月にリリースしたばかりのマーケティングオートメーションプラットフォームで、社内では比較的若いプロジェクトです。そのため、MAJINでは他のプロジェクトよりトレンディな技術を多く採用する傾向があります。

ローンチの時にはフロントエンドとバックエンドを分けて別々で開発する体制をとりましたが、最近はチーム内の交流が増え、フルスタックエンジニアを目指すチームメンバーも急増しました。

今回は「フロントエンド」をテーマとしていますが、JavascriptやHTMLを使ったWebサイトの設計・実装といった「狭義のフロントエンド」ではなく、DBのデータを取得や更新する為のサーバ側の設計・実装(API等)も含めた「広義のフロントエンド」と定義させていただきます。

技術沿革

  • ローンチ時のフロントエンド:PHP 7 + Symfony 3.x + ES6 + Vue.js 1.x
  • 最近のフロントエンド: Python 3.5 + Flask + ES6 + Vue.js 2.x

PHP+Symfonyを選んだ&やめた理由

PHP+Symfonyを選んだ一番最初の理由は、社内で既に使われていて短期間にエンジニアを確保しやすいところでした。しかし、MAJINの開発加速に伴い、PHP+Symfonyの限界を徐々に感じました。

  • MAJINではRDBMSのMySQLの他に、DynamoDBやAerospikeなどのNoSQL系のデータベースも使用しています。これらDBに対し、Symfonyのジェネレータ(Ruby on Rails の scaffolding に相当)やORMapperなどの機能のメリットをほとんど生かせませんでした。例えば最初にDoctrine Annotation ReaderでDynamoDB用のORMapperを作りましたが、クエリの性能とデータ一貫性のコントロールを考慮して結局AWS SDKをそのまま使うことにしました。
  • MAJINのフロントエンドの他のマイクロサービスのAPIとのやりとりが想定よりも多くなりました。これらのAPIで処理する機能にさらにSymfonyのようなフレームワークを挟むとオーバーヘッドが増えます。デバッグとテストもやりにくくなります。
  • MAJINの仕様上、コンテンツやシナリオなどのビジネス要件にはリッチな画面が要求されています。フロントエンドのSPA化(Single-Page Application)によってSymfonyの存在感がさらに薄れました。

Python 3.5+Flaskを選んだ理由

  • 一部のバックエンドとAPIがPython 3.5で書かれているのでコードを共有ができ、PHPで車輪の再発明をせずに工数を節約できます。
  • Flaskは手軽で軽量でウェブアプリケーションフレームワークとして使いやすいです。ライブラリも豊富で特に不自由さを感じません。
  • Flaskは自由度が高いので、必要に応じて機能の拡張も簡単にできます。MAJINにも開発効率向上のためにFlaskでいくつかのプラグインを開発しました。

ES6+Vue.jsを選んだ理由

[f:id:tech-geniee:20170718181028j:plain]

モダンなSPAの開発にはMVVM(Model–view–viewmodel)フレームワークが不可欠です。数多く存在するMVVMフレームワークの中でも、下記の理由でVue.jsを選びました。

  • 使い方が簡単、勉強コストが低い。
  • Monolithicなフレームワークではなく、初めから少しづつ適用していける(Progressive framework)。
  • 理論上と実際の性能がよかった。

Vue.jsの実装はごく簡単で、下記のようにModel,View,ViewModelをそれぞれ定義するだけで、入力値が即Modelに保存され、Model内の値もすぐViewに反映されます。一見簡単そうな仕組みですが、データフローを正確に定義することによって大規模な開発に莫大な威力を発揮できます。

<p data-height=”265″ data-theme-id=”0″ data-slug-hash=”GEYGgX” data-default-tab=”html,result” data-user=”cheungchifung” data-embed-version=”2″ data-pen-title=”Example of two-way binding” class=”codepen”>See the Pen <a href=”https://codepen.io/cheungchifung/pen/GEYGgX/”>Example of two-way binding</a> by Cheung Chifung (<a href=”https://codepen.io/cheungchifung”>@cheungchifung</a>) on <a href=”https://codepen.io”>CodePen</a>.</p>
<script async src=”https://production-assets.codepen.io/assets/embed/ei.js”></script>

“`html
<div id=”main_view”>
<label for=”name”>Enter name:</label>
<input type=”text” v-model=”name” id=”name” name=”name” />
<p>Welcome, {{ name }}!</p>
</div>
“`

世の中のMVVMフレームワークのReactiveの実装はいくつもあります。[参考](https://teropa.info/blog/2015/03/02/change-and-its-detection-in-javascript-frameworks.html)

    • – Pub-Sub(backbone.js): pub, subの方式でデータを更新する。
    • – Dirty Checking(augular.js): click等の特定のイベントが発火したらデータの更新検知を行う。
    • – Virtual DOM(React): Virtual DOMを用いて、Modelの変化を高速にViewに反映する。
    • – Hook(Vue.js): ECMAScript5の`Object.defineProperty()`を利用して値の変化を検知し、変化があったらSubscriberにメッセージを送りコールバックを呼ぶ。(2.0からVue.jsもVirtual DOMを導入した)

Vue.jsが`Object.defineProperty`を使うことで、`this.name = “MAJIN”`のように書くだけで、Observer(Vue.jsで変化を監視するコンポネート)が自動的に変化を検出してテンプレートに反映され、開発はかなり楽になります。その代わり、IE8以下などのECMAScript5未対応のブラウザは対応できません。
(MAJINのサポートブラウザは全てES5対応なので問題ありませんでした)
Vue.jsのReactiveの仕組みを詳しく説明したいところですが、今回は割愛します。

また、Vue.jsの公式の[比較記事](https://jp.vuejs.org/v2/guide/comparison.html)によると、Vue.jsはReactに劣らないパフォーマンスを提供できます。MAJINではVue.js 1.0と2.0を使っていますが、性能面の問題は特に感じませんでした。(と言っても使い方次第でパフォーマンスが落ちることはもちろんあります。例えば検知不要な値を大量にObserverに突っ込んでブラウザが固まることもあります)

当初Vue.jsを選んだ時、公式のデモで使われていたES6をそのまま導入しましたが、ES6には型チェックがないので心細く、TypeScriptに乗り換えようと試みたこともあります。しかし、当時はTypeScriptとVue.jsの相性が悪く感じ、挫折してしまいました。
最近Vue.jsとTypeScriptを取り巻く環境も大きく変わりましたので、そろそろ再チャレンジしようと思います。

Vue.jsでハマったところ

Vue 1.x から 2.x

MAJINリリース時に2.xはまだstableになっていないため、古いコードは全部1.xを使いました。

2.xではいろんな特性が追加されましたが、特にアップグレードしなければならない理由が無く、そのまま放置しようと思いました。しかしVue.js 2.0リリース後半年も経たず、多くのプラグインが2.0にしか対応しない状態になってしまって、止むを得ずにVue.js 2.0に移行しました。

2.0へ移行するには、書き直しが必要な箇所が多く思ったより大変でした。MAJINは複数のエンドポイントでVue.jsを使っているので、vue1.xと2.xのページのwebpackファイルを分けて少しずつ移行することにしました。Vue.js 1.xに書いたUIコンポーネントもVue.js 2.xでそのまま動かないので、一部のUIコンポーネントも2.0版で書き直しました。

移行は辛かったですが、1.xと比べて使えるライブラリが増え、Virtual DOMなどの2.xのメリットを手に入れたので、移行する価値はあると思います。

エコシステムが未熟

Vue.js 1.0を導入する時にすでにVuex(ReactのReduxのVue.js版)やVue-routerがすでに出ましたが、多くのVue.jsのライブラリはまだ使いづらいものでした。最近はある程度改善されたようですが、いざという時にはやはり自力でカスタマイズするしかありません。

解決案は主に二つ:

        1. . jQueryなどのライブラリのVue.js版を作る。
        2. . 自分でVue.jsのプラグインを作る。

1についてはVue.jsの公式サイトに[デモ](https://vuejs.org/v2/examples/select2.html)があります。多くのUIコンポーネントはこちらの方法で対応しました。Vue.jsには様々なUIのライブラリが存在していますが、MAJINに合うものはなかなか見つからず、従来のUIライブラリをこの方法で流用し、Vue.jsに対応しました。

2は難しそうに見えますが、実は簡単でした。Vue.jsのプラグインを作ることで、既存のシステムから移行する時にそのギャップを埋められる重要な手法です。ここでは一番簡単なMAJINの「i18nプラグイン」を使って説明いたします(説明の便宜上、言語を日本語に固定します)。

`plugins/i18n.js`

“`javascript
import campaign from ‘i18n/campaign.ja.yml’
import _ from ‘lodash’

const i18nMaster = {
campaign,
}

let i18nCache = {} // In-memory Cache

export const translate = (expression) => {
if (i18nCache[expression] !== undefined) {
return i18nCache[expression]
}

const paths = expression.split(‘.’)
let f = (_paths, master) => {
try {
let p = _paths.shift()
let v = master[p]
return typeof master === ‘string’ ? master : f(_paths, v)
} catch (e) {
if (__DEV__) console.warn(`[i18n] cannot find expression: ${expression}`)
return null
}
}
let v = f(paths, i18nMaster)
if (v !== null) {
i18nCache[expression] = v
}
return v
}

function I18n (Vue) {
// Step 1: プラグインがインストール済みかのチェック
if (I18n.installed) return
I18n.installed = true

// Step 2: Mixinでコードを入れる
Vue.mixin({
beforeCreate() {
Object.defineProperty(this, “translate”, {
value: translate,
})

Vue.filter(‘translate’, translate)
},
})
}

export default I18n
“`

このプラグインの目的は、Symfony形式のyamlのi18nの定義ファイルをそのままVue.jsで使い回すことです。
冒頭の`i18n/campaigin.js.yml`は今回使うi18nファイルの名前であり、その中の `i18n` は `webpack.config.js`で設定したパスです。

`webpack.config.js(抜粋)`

“`javascript
resolve: {
“alias”: {
“i18n”: __dirname + “/path/to/translations”,
}
}
“`

`npm install yaml-loader`して`webpack.config.js`に下記のコードを追加すると、i18nの定義ファイルはJavaScript Objectとして読み込まれます。

“`javascript
module: {
loaders: [

{
test: /\.(yaml|yml)$/,
loader: “json!yaml”
},

],
}
“`

そしてエンドポイントファイルに
“`javascript
Vue.use(I18n)
“`
を追加すれば、ViewModelで使えます。

“`javascript
var myApp = new Vue({
el: ‘#ma-app’,
data(): {
return {
message: this.translate(‘campaign.path.to.translate’)
}
},
})
“`

またはViewでfilterとして使えます。

“`html
<span>{{ ‘campaign.path.to.translate’ | translate }}</span>
“`

MAJINでは、i18nのほか認証やValidatorなどのプラグインも自作しました。これらのプラグインを利用しフロントエンドのシステム移行を加速できました。

ビルド時間が長い

Vue.jsで書かれたコードの増加に伴い、ビルド時間が急増しました。また、Webpackのビルド時のCPUとメモリの消費率もかなり高まり、ひどい時はAWS上のJenkinsがOutOfMemoryで死ぬこともありました。

この問題の解決案は二つあります。

        1. . `webpack.optimize.CommonsChunkPlugin`を利用して重複ビルドを省く。(マルチエンドポイントのMAJINでは大きな効果がありました)
        2. . `HappyPack`(https://github.com/amireh/happypack)でビルド処理を非同期化する。

この二つの手段の組み合わせで、本来10分以上かかったビルドが、今は2分弱で完了します。

終わりに

MAJINのフロントエンドで使った技術を選んだ理由とそれぞれの問題点を簡単に紹介しました。より細かい話は、これからのブログで随時掲載いたします。
どうぞご期待ください。

Date
Author
エンジニアの視点から、様々な技術、サービス開発秘話、イベントをご紹介していきます。 ジーニーエンジニアチーム

はじめに

みなさん始めまして、R&D本部 基盤技術開発部の石田祥英です。
北大の情報科学研究科を卒業前に飛び出しジーニーに半年早く17卒入社し、現在は主にFlink, Kafka, Play Framework(scala)や、バッチ用途でgolang,pythonなどを使いプロダクト横断のシステムの開発・検証をやっています。

TL;DR

  • ClickHouseで分析系クエリが1000倍の速度に爆速化
  • DBの容量もMySQLと比べ1/13に軽量化
  • ClickHouse導入はMySQLには無い制限もあるけど、なんとかなる
  • あんまり日本での導入事例が見当たら無いけど、クエリの高速化・DBの軽量化したい人はぜひ使うといいことがあるかもしれません

社内勉強会用の資料

ClickHouse導入の背景

一般的に広告プラットフォームでは「どの広告を、どの広告枠(サイト)に、いつ、どのように(RTB or Adnetwork)配信したのか」という様な情報をDBに格納し、広告主向けの管理画面がDBからレポートする内容を取得し、代理店や広告主の運用者に配信結果をレポート表示しています。

通常、「〜ごとのレポートを見たい」となった場合、それに相当するカラムをキーとして保存しなくてはいけません。

しかし、実際には「1日ではなく1時間ごとにレポートを見たい」、「OS、地域、デバイスごとなどのImpression(広告表示)や広告のClickを集計したい」となると、キーがどんどん増え、それに伴ってDBの行数が指数関数的に増えていってしまいます。

1日に15TBほどの広告配信のログが出るジーニーでは、実際にキーの数を4個から10個に増やそうとした時に、もうMySQLではインデックスを正しく張って頑張っても、運用者が我慢できる時間内にクエリが返ってこなくなってしまう、という問題にぶち当たっていました。

また事業成長の要因も考慮し、トラフィックが10倍に増えても低レイテンシでレポートを返すDBが求められており、何か手はないのかと言うことで色々な方法を模索していました。

DBに必要な要件

  • 広告の運用者の方々がレポート画面をみて運用のPDCAを回せるように、とにかく低レイテンシであること
  • 集計プログラムにバグが見つかった時に再集計してDBの内容を正せること
  • ログ転送遅延時やハードウェア故障時などへの耐障害性があること

検証した他サービス・手法

MySQLに並列でクエリを投げる

レポートAPIがscalaのPlayで書かれていることもあり、akkaを使い並列でクエリを投げる案があったのですが、正しくソートされたレポートを並列化されたクエリでうまくかける方法が見つからず実現が難しいと判断しました。

BigQuery

Googleの巨大なリソースを使い、SaaSであるので開発・メンテが不要なことやSQLライクなインターフェースと柔軟なUDFが魅力で検討対象に。

実データでの検証は行なっていませんが、Google社の営業担当にテーブルの行数とそれに対するクエリのベンチマークの結果を教えてもらい、それをクエリのパフォーマンスとして考えることができました。

BigQueryはクエリごとの課金とデータ量による課金があり、クエリ課金部分は月額3万ドル(2016/12時点)で叩き放題のプランがりましたが、データ量が膨大なことにより予算をオーバーしたことと、そもそもAPI向けの秒単位の低レイテンシ用途に最適ではないと判断し諦めることになりました。

InfoBright

MySQL上にビルドされたカラムナDB。列志向による軽量化と高速化が期待できる上、MySQLからの移行もスムーズに行えそうなことが魅力に映り実データでの検証に至りました。

しかしユニークキーがはれないことや、INSERT 〜 ON DUPLICATE KEY UPDATEができない、頻繁なアップデートに不向きで、特別な運用をしないといけないことに加え、手元のデータではClickHouseよりもクエリ性能が出なかったこともあり今回は使用しないことになりました。

ClickHouse

公式HPにMySQL・VerticaやInfoBrightなどのカラムナDB・Hiveとのベンチマークを乗せており、ほとんどの場合で、高速なことが魅力でした。特にレポートで頻出するSum関数やGroup By句でのパフォーマンスが高く、実データでの検証に至りました。特にフリーかつオープンソースであること、何よりドキュメントがしっかりしていたことも大きな魅力でした。

https://clickhouse.yandex/benchmark.html

ClickHouseの性質・性能

スキャンする性能がものすごく高い

手元の検証用データではスキャン性能 3億行/s 9GB/sほど出る。(後述のSumming Merge Treeエンジン使用時)

圧縮率が高くストレージの節約になる

カラムナDBなので圧縮率が高い。
検証用データ使用時にはMySQLに比べてストレージ使用量が1/13になりました。

ただし後述のMergeテーブルを使い、1つのテーブルを450テーブルに分散した状態で測定したので、1テーブルで行った場合にはさらに圧縮されるポテンシャルがあると考えられます。

多種多様なテーブルエンジンがある

ClickHouseには20種類のテーブルエンジンがあり、CREATE TABLE時に1つorいくつか組み合わせて選んでテーブルを作ります。

This is the most advanced table engine in ClickHouse. Don’t confuse it with the Merge engine.

とドキュメントにあるように、Merge TreeエンジンがClickHouseに置ける看板エンジンであり、広告主向けレポートで使用したテーブルもMerge Treeエンジンの亜種であるSumming Merge Treeエンジンを使用しています。

広告主向けレポートで使用している2つのテーブルエンジンを紹介しようと思います。

Summing MergeTreeエンジン

Summing Merge Treeエンジンは足し上げが起こるレポート等の用途に向いているエンジンです。キーになるカラムとメジャーとなるカラムを指定しておき、同じキーのレコードをinsertするとメジャーは足し上げられて一行として扱われるようになるという性質を持ちます。ImpressionやClick数、広告主にかかるコストなど、足し上げが発生するレポートにおいては非常に便利なテーブルエンジンで広告向けレポートにはピッタリでした。ClickHouseの行のUPDATEができないという問題も、足し上げるだけのためのUPDATEであればこのエンジンを使うだけで問題なくなります。

Mergeエンジン

Mergeエンジンは複数のテーブルを1つのテーブルとして扱うエンジンです。

テーブル作成時にテーブルの正規表現を指定しておくと、それにマッチした複数のテーブルを1つのテーブルとして扱い、Mergeエンジンにクエリを投げれば配下のDBにクエリを投げた結果を返してくれるという性質を持つため、巨大なテーブルを分割して保存しておくことが可能になります。

UPDATE・DELETEがない

ClickHouseでは行に対するUPDATEとDELETEができません

これがClickHouseの性能に飛びつくも導入時に困るであろう大きな問題で、今回広告主向けレポートではどう乗り越えたかを紹介したいと思います。

ClickHouseの運用

困ったこと

SQLはほぼMySQLと同じであり、ClickHouse移行で最大にして唯一困ることは

「UPDATE・DELETEが無い問題」

でした。

具体的には

  1. UPDATEができないので、同じ行への更新ができない。
  2. DELETEができないので、集計プログラムのバグ発覚や、集計遅延時等にDB内のデータ修正ができない。行う場合は、DROP TABLEしてまた正しいデータを入れ直さないといけないため時間がかかる。

といった問題にぶつかりました。

今回の広告主向けレポートの要件として

  1. 1時間ごとの集計
  2. 再集計が短時間で可能

というものがあり、要件を満たしながら制限を回避する方法にたどり着きました。

 乗り越え方

簡単に箇条書きにすると

  • Mergeエンジンを使い1日ごとにテーブルを作成することで、データが壊れた時のデータの入れ直しの時間を減らす。
  • Summing Merge Treeエンジンを使い、1時間ごとに最新データを入れていく。同じキーごとにメジャーが足し上げられるので、同じ行のimpressionやclick数などのメジャーの集計が遅れても正しく足し上げられる。
  • RENAME句のみがトランザクションを使える(複数テーブルの一括RENAME時にグローバルロックが走る)ので、それを使って壊れたデータと正しいデータに入れ替えを行う。

ここら辺は文字で書くとややこしいので冒頭のスライドにデータの入れ直しのテクニックを図解しているので参照してみてください。

ClickHouseの苦手だと感じたこと

非常に派手なベンチマークのClickHouseも以下の用途には向かない(そもそもそれ用に設計されてない)です。

OLTP処理

ClickHouseはそもそもがOLAP処理に作られたDBであり、トランザクション処理も実装していません。唯一RENAME句内での複数RENAMEにグローバルロックがかかるぐらいです。ECなどのトランザクション取引が発生するサービスのDBとしては向いていません。

分散ストリーミング環境からののインサート

ドキュメントに

 We recommend inserting data in packets of at least 1000 rows, or no more than a single request per second

とあるよう1回のINSERTには1秒あけることと少なくとも1000行のデータをINSERTすることが推奨されており、ストリーミング処理したデータをポイポイ入れていくのではなく、ストリーミングの場合はどこかに一度貯めてからバッチ的にINSERTする必要があるようです。

分散処理基盤からのインサート

また広告主向けレポートでも現在Apache KafkaとApache Flinkなどを用いて分散ストリーミング処理を今後行っていくつもりですが、Apache kafkaやApache Flinkで分散したデータを最終的には1つのtsvファイルにまとめる必要があり、分散したままのINSERTには向いていないようです

https://clickhouse.yandex/docs/en/single/#performance-on-data-insertion

まとめ

社内の広告運用者からは「ロードに3分かかっていたレポート画面が0.5秒で返ってくるようになりました!」と感謝され、DBAからは「DBを圧迫していたレポートテーブルが小さくなった」と喜びの声をいただきました。

現状の使い方ではレプリケーションしかしていませんが、今後格納行数がさらに大きくなった時にもShardingしながら分散するDistributeテーブルエンジンもあるので、まだクエリが遅くなることがすぐに起こる予定はないですが、そちらを使って対処していこうかと思います。 ClickHouseの開発元であるYandex社では374台のサーバーに20兆行を超えるデータが入っているようです。

最後に、大規模なデータを持っていて超早い分析系のクエリを求めるプロダクト(アドテク、EC、ゲーム・メディアのユーザ分析等)なら本当に検証の価値ありだと思います。クエリが相当早くなりますし、データも軽量になります。

また、本番投入できるかの見極めについては、 「データ入れ直しが許容時間内に終わる見通し」が立つのであるならば本番投入できる可能性が高いと言えるのではないかと考えています。

https://clickhouse.yandex/docs/en/single/index.html#distributed

以上。

Date
Author
エンジニアの視点から、様々な技術、サービス開発秘話、イベントをご紹介していきます。 ジーニーエンジニアチーム

はじめまして。このブログの編集長を務めることになりました、R&D本部マーケティングオートメーション開発部の張です。ジーニーへは、2016年4月に入社して、主にフロントエンドを担当しています。

初回ということで、CTOの篠塚とブログを始めるきっかけや、ジーニーの開発部門の紹介をさせていただきます。

(写真左:CTO・篠塚 英伸、右:エンジニアブログ編集長・張 志鋒)

ブログを始めるワケ

張:

ジーニーは、結構、面白い技術を使っていて、色々発信したいと思っていたんです。でも、ブログもなく、あまり社外に伝える機会がないな、と思っていました。

篠塚(CTO):

そうですね。R&D本部全体では、「誇れるものをつくろう」といつも言っているので、「誇れるものをつくったら、自慢しなきゃ!」と。それを発信していきたいというのが、このブログを始めた1つのきっかけですね。
あと、自分で勉強して、プロダクト開発に反映させて、「よかったね」と。それはそれで良いんですけど、エンジニアのキャリアやスキルアップを考えると、社内外の場でお互いに共有したり、発信したりしていくのも大事。そこでいろんな人からフィードバックを得て、ブラッシュアップしていく方が成長できると思うんですよ。

張:
このブログを通して、優秀なエンジニアの方たちにジーニーの技術を知ってもらいたいし、それによって、友を呼びたいですね。

篠塚:
ジーニーは、あまり中のことを語らない人たちが多いけれど、アドテク自体がマニアックなので、おもしろい内容が書けるんじゃないかと思うんです。アドテクノロジーやマーケティングテクノロジーについて、興味を持ってくれるエンジニアが増えたらいいなと。そして、仲間が増えたら嬉しいですね。

ジーニーのエンジニアリング部門

篠塚:
R&D本部には、「アド・プラットフォーム開発部」「マーケティングオートメーション開発部」「基盤技術開発部」「経営情報システム開発部」の4つの部があり、それぞれ25人・15人・10人・10人で合計60人ぐらいいます。

張:
メンバーのバックグラウンドは、コンピュータサイエンス系が多いですが、文系の人もいれば、美大(アート)出身者もいて、面白い人が集まっています。ちなみに僕は経済学部でした。

篠塚:
張さん、文系だったんだ!びっくり。
新卒も8割くらいはコンピュータサイエンス出身ですね。理工系も少しいます。

張:
中途では、1/3ぐらいがアドテク出身で、SI出身も多いですね。あとは、ゲーム系とか、Webサービス系とか、いろんなバックグラウンドの人がいると思います。

篠塚:
総じて、尖っている人が多い気がしますね。みんなそれぞれ特長的。
あと、女性は現状2名しかいません!

張:
特にアドテク業界は、女性が少ないんですかね?!

篠塚:
アドテク女子って、本当に少ない(笑)

張:
ジーニーは、女性も働きやすい環境ではあると思うんですけど。

篠塚:
男性も育休取っていますし。エンジニアではないですが、女性社員で産休育休をとって復帰している前例もあります。女性の感性がもっとプロダクトに入ると、いいと思うんですよね。

仕事の仕方や雰囲気

張:
僕は、何でも屋ですね。以前は、フロントエンドとバックエンドが分かれていましたが、最近は、一緒に仕事をするようになってきています。タスクに対して、みんなで力を合わせてやるフルスタックというイメージです。

篠塚:
そうですね、インフラは分かれていますが、フルスタックを目指しています。
もちろん、人によって得意領域はあるけれど、他の人の業務を知らないと、最適な設計ができないと思います。
これまで規模が小さい頃は、とにかくスピード重視で役割を分けてやってきました。しかし、規模も大きくなり、今後、ジーニープラットフォームとして連携していくことを考えると、技術的な切り分けではなく、タスクの解決方法に合わせて分担していく方がいいと考えています。そのためには、エンジニア1人ひとりが広範囲のことを知らなければいけないですね。

張:
もちろん初めから全部できる、というのは難しいですが、例えば、データベースは何を使っているかとか、どういう構成で何を処理しているかなど、プロダクトを知らないと、フロントでもアプリケーションでもモノづくりはできません。お互いを知らないと、チームとして動けないんですよね。

篠塚:
この体制は、特長的かもしれませんね。

張:
最近は、チームを越えてお互いを知るようになってきたと思います。もっともっと、壁をなくしていきたいですね。そのための1つの方法として、週1回社内勉強会をやっています。こちらのチームでは新技術を使って開発しているのに、隣のチームはよくわからない、というのではもったいないですから。プログラミング業界でよく言われるような“車輪の再発明”とかしたくないからね。知識が共有できれば、ジーニーの開発パワーはもっと上がってくると思うんです。

篠塚:
勉強会のほかには、月に一度、R&Dの全体会があります。メンバー持ち回りでLTをやっているんですけど、わりと面白いですよ。飲み会とかより、ずっと盛り上がるんです。この前のLTでは、あるメンバーが「モテたいから髪色を変えたい」ということで、似合う色を判定するためだけの仕組みをわざわざAI使って作ってみましたって発表がありました。みんな大爆笑でしたよ。「変えればいいじゃん!」って。そんな雰囲気の部門です(笑)

ジーニーならではのこと

篠塚:
普段よく目に触れるWebサービスは、UIを提供するのが一般的ですが、アドテクやマーケティングオートメーションでは、見える部分がほとんどありません。表には出ませんが、例えば、潜在顧客に1通メールを出したり、1つバナー広告が表示されたりするまでには、いろいろなドラマがあるんですよ!データを集めて、次も出すべきかどうかというスコアリングや分析をして、良かったのか悪かったのか、その結果をフィードバックする仕組みは、顧客のマーケティング施策全体や業績に大きく関わってきます。目に見える部分はほんのわずかですが、裏側ではけっこう壮大なことをやっているんですよ。

張:
MAJIN(マーケティングオートメーションツール)も、目に見えないところで結構頑張っているんですよ。MAJINは、フロントもバックもなかなか複雑で、データベースの開発とかにも手を出そうとしています。最先端の論文で研究して技術を実装してみたり、普通ならあまり使わない言語を使ってみたり、いろいろ試して、改善して、結果どんどん良くなっています。ジーニーの場合、実験的な試みや失敗も許容してくれる環境があるので、最先端の技術にチャレンジできるのがいいですね。

篠塚:
他社が採用していないような技術も、積極的に研究したり、実験的に採用したり、産学連携したり。いろいろやっていることを活かして、オープンソースへの貢献もしていきたいですね。

張:
新しい技術の開発は、他社だとあまり裁量権がもらえないことが多いと思うんです。僕の場合、どんどん勉強して、実際に試せるというのは、ジーニーに入って良かったことの1つだと思います。

篠塚:
営業のみんなが頑張ってくれているから、エンジニアにチャレンジできる余裕が生まれるので、ありがたいですね。いい循環が生まれていると思います。
あと、ジーニーの特徴として、データ量(トラフィック)が多いことがあります。1日のデータ処理量は、だいたい15テラくらいあるんですが、それを効率よく24時間365日動かし続けなければいけない環境って、わりと珍しいと思うんですよ。

張:
MAJINの方では、機械学習も強化していますし、AI活用も進んでくるので、そういうチャレンジをしたい方にもいい環境だと思います。

アドテクノロジーで世界を変える(=ジーニーのミッション)

篠塚:
世の中にまだ解決できてない課題があって、それを解決すると、少し世界がよくなります。なぜ、いろいろな課題が解決できないかというと、アイデアがないわけではなくて、いろいろな困難があって越えられないんですよ。
顧客の本質的な課題にしっかり応えるために、必要な技術を見極めて、ベストなものを真面目につくる。有り体のものを使うのではなく、自分たちにしかできないものを自分たちの手でつくるんです。課題自体がどんどん複雑になっているので、必然的に最先端の技術を取り入れていかなければならないわけです。そうやって、1つずつ課題を解決していくと、世の中が良くなっていくんです。それが僕たちのミッションだし、それができると「誇れるものがつくれた」ということになります。

張:
その通りです。困難があって、他の人が解決できなかったことを、僕らがエンジニアリングで解決できたら達成感がありますよね。

篠塚:
MAだったら、どこまでオートメーションにすると、本当にマーケターが楽になるかとか、人では思いつかない(できない)成果が得られるかとか。そういった壁を一つひとつ解決していくことが大事だと思っています。

張:
こんな僕たちの学びとか気づきとか、勉強会や研究について、このブログで発信していきたいと思っています。
よろしくお願いします!

Date
Author
エンジニアの視点から、様々な技術、サービス開発秘話、イベントをご紹介していきます。 ジーニーエンジニアチーム
Back to top