LIVESENSE made*

リブセンスのエンジニアやデザイナーの活動や注目していることをまとめたブログです。

MENU

データ分析を支える「便利カラム」の問題点とその解決策

こんにちは、'16新卒入社で、Analyticsグループ所属の田中です。 仕事ではデータ分析基盤や機械学習システムの開発・運用を行っています。

今回はデータ分析基盤における「便利カラム」にまつわる問題と、それを解決するためのアーキテクチャについてご紹介します。

リブセンスのデータ分析基盤

みなさんの会社では、サービスのデータ分析をどのように行っていますか?

リブセンスにはデータ分析・活用の文化が根付いており、ディレクターや営業職の社員までもがSQLを用いてKPIのモニタリングや施策の評価を行っています。 分析活動を支えるために、社内では “Livesense Analytics” という全社横断のデータ分析基盤を構築・運用しています。

このような組織が形成されるまでのポイントについては次の資料で解説しています。

営業さんまで、社員全員がSQLを使う 「越境型組織」 ができるまでの3+1のポイント | リブセンス

Livesense Analyticsの全貌については次の資料で紹介しています。

リブセンスのデータ分析基盤の全貌 // Speaker Deck

少人数のチームで基盤を開発・運用するため、システムはAWS上に構築しています。 中核となる分析DBにはAmazon Redshiftを利用しており、数億件のレコードを集計するようなSQLを数秒から数分で実行することができます。

集計簡単化のための「便利カラム」

分析DBにはアプリケーションデータだけでなく、PVログのようなユーザの行動ログも保存しています。 これらのログにはURLや訪問日時などの生データに加えて、それらを加工して得られる二次データを付与しています。 この二次データ、いわゆる「便利カラム」には次のような値が含まれます。

  • URLをサービスの機能ごとに分類したページ種別
  • 連続する複数のPVをまとめるセッションID

これらのデータがあることで、ページ毎のPV数や複数PVにまたがるユーザ行動の持続時間の集計が簡単になります。

f:id:livesense-made:20170417160913p:plain

問題点1: 便利カラムの値の修正ができない

データ分析基盤を継続的に運用していると、しばしば便利カラムの値を修正したいことがあります。 例えば「これまでは前回PVから30分以上経過すればセッションが切れたとみなしていたが、その閾値を15分に短縮したい」といったケースです。

しかし、一旦DBに投入された過去データについては修正が難しい場合があります。 これは便利カラムの値がクライアントサイドやログ収集サーバで生成されているときに起こります。

以前のLivesense Analyticsでは、セッションIDはCookieに保存された前回PVのタイムスタンプをもとに生成されており、ページ種別はログ収集サーバで判定されていました。 このため、分析DBにログが投入されてからセッションの切れ目を変更するといったことは事実上不可能でした。

f:id:livesense-made:20170417160920p:plain

この問題の主な要因は、生データから二次データを生成するロジックの変更が想定されていないことです。

セッションIDなどの二次データは、URLやタイムスタンプなどの「事実」とは異なり、生データに対する「解釈」から生まれます。 セッション持続時間の閾値の例のが示すとおり、この解釈ルールは変更される可能性があります。 そのことが事前に想定されていなければ、あとからロジックの変更を適用することが難しくなってしまいます。

解決策1: バッチ層の導入

ロジックの変更を過去のデータに遡って適用するには、もとの生データから二次データを何度でも再生成できる仕組みが必要です。

そこで生データをAmazon S3などのストレージに保存し、バッチ処理で二次データを再生成する層を導入します。

f:id:livesense-made:20170417161227p:plain

通常の場合はバッチ処理を1日1回程度定期的に実行し、その都度に新たな生データから二次データを生成してDBに投入します。

二次データの生成ロジックに変更が生じた場合、バッチ処理の実装を変更し、過去の全ての生データから二次データを再生成してDBの中身を入替えます。

後者では蓄積された大量の生データを処理する必要がありますが、あらかじめHadoop MapReduceのような分散処理基盤を利用しておけば、処理の実装を切り替えずに済みます。 Amazon Elastic Mapreduce (EMR)などのオンデマンドサービスを使えば、必要に応じてクラスタを立ち上げられるため、コストを抑えることができます。

問題点2: バッチ処理の複雑化とパフォーマンス低下

バッチ層の導入によって「便利カラム問題」は解決できそうです。 しかしこの仕組みを長期的に運用しているといくつかの問題が生じると考えられます。

まず、生データが細切れになっているとバッチ処理のオーバーヘッドが増大してしまうことがあります。 ログが短い間隔でバッファリングされている場合、生データは数MB〜数十MB単位の細切れになったオブジェクトとして蓄積されます。 これらの大量のオブジェクトの読込にオーバーヘッドがかかると、全データのバッチ処理のパフォーマンスが低下してしまいます。

また、ログ収集時の都合により生データの構造がバッチ処理に適していないことがあります。 例えばユーザのマウスイベントを複数件束ねてログ収集サーバににPOSTしている場合、イベントを集計する処理を行う前にそれらを複数のレコードに分解する必要があります。

f:id:livesense-made:20170417161232p:plain

個々の問題はそれほど複雑には見えないかもしれませんが、長期間にわたって生データをログ収集時のまま保存していると、いざ全件処理を行いたいときに時間がかかったりエラーが発生といった問題が起こり得ます。

解決策2: マスタデータ層の導入

バッチ処理の複雑化やパフォーマンスの低下を招く主な要因は、バッチ層が次の2つの処理を同時に行っていることです。

  1. 生データをバッチ処理に適した形に整形する
  2. 整形されたデータから二次データを生成する

特に1.は二次データの生成ロジックとは独立しており、本来データ収集時に一度行うだけで済むはずです。 そこで、生データに対する一度きりの加工処理を行うためのマスタデータ層を導入します。

f:id:livesense-made:20170417161240p:plain

このマスタデータ層では、生データを次のような性質を満たすよう加工します。

  • 解釈によって変わることのない一次データのみを保持している
  • オブジェクトの粒度や形式がバッチ処理に適した状態になっている

二次データの生成処理とは異なり、マスタデータ層では定期的な差分処理のみを考えればよく、過去ログに対する全件処理は通常発生しません。 マスタデータ層を設けることで、二次データの生成処理をシンプルに保ち、パフォーマンスを向上させることができます。

ラムダアーキテクチャに向けて

実は上記のアーキテクチャは、ラムダアーキテクチャと呼ばれるデータ分析基盤の設計指針を参考にしたものです。

Lambda Architecture » λ lambda-architecture.net

本来のラムダアーキテクチャでは、データがマスタデータ層・バッチ層を通って利用可能となるのを待たずに速報値の分析ができるよう、スピード層と呼ばれる別のデータフローを構築します。 しかし今回の要件ではリアルタイム性は求められない(前日までのログが利用可能であればよい)ため、スピード層は用意していません。

この記事では説明しませんが、ラムダアーキテクチャについて詳しく知りたい方には次の書籍をおすすめします。

O'Reilly Japan - スケーラブルリアルタイムデータ分析入門

バッチ層・マスタデータ層に使われる技術

さて、ここまでバッチ層・マスタデータ層のアーキテクチャについて説明してきました。 最後にこれを実現した技術スタックを簡単にご紹介します。

もともとの分析基盤をAWS上に構築していたため、新しく開発したバッチ層・マスタデータ層でもAWSのサービスを活用しました。 生データ・マスタデータを保存するストレージにはS3、分散処理基盤にはEMRを採用しました。

分散処理フレームワークにはApache Spark (2系)を採用しました。 実装言語にはSpark本体の実装にも使われているScalaを採用し、パフォーマンスと型安全性を両立させるためDataset APIを用いて処理を記述しています。

開発で得られた知見は以下のような記事でも紹介しています。

yubessy.hatenablog.com

今後機会があれば実装に関するノウハウなども共有していきたいと思います。

おわりに

長くなりましたが、最後までおつきあいいただきありがとうございました。 今後もこのブログでは分析基盤やデータ活用に関する内容を投稿していきますので、どうぞご期待下さい。

事業を推進するために必要なエンジニアスキル

こんにちは、新卒2年目エンジニアの片岡です。 正社員転職メディア『ジョブセンスリンク』の開発を行っています。

job.j-sen.jp

リブセンスには職種の『越境』文化が根付いています。 セールスに必要なデータは営業担当者が自らSQLを書いて用意します。 エンジニアがディレクター的な働きをして機能設計に深く関わることはリブセンスにおいて自然です。

このような環境下で、私は『開発者の立場から事業を推進する』という指針を持って他職種の方たちと協働しながら開発を行ってきました。

『事業を推進するエンジニアに求められるスキル・姿勢とは?』という自らに課した問いに対して、新卒としてリブセンスで2年間を過ごした経験からたどり着いた自分なりの答えを共有させていただきます。

事業を推進するエンジニアに求められるスキル・姿勢とは

1.危機感を持って技術を学び続ける

入社当初、事業を推進するためには事業ドメインの理解やマネジメントなど「技術以外の総合力」が求められると私は思っていました。

しかし実務経験を経た今考え直すとむしろ逆で、事業を推進するエンジニアにこそ技術が求められるのだと感じています。 設計・コーディング・プロジェクト管理など様々な技術がなければ中長期的に見て効率的な開発を続けることができないからです。 変化の早い業界ですから、継続的に新技術のキャッチアップを行うことも必要です。

課題に対し、解決できる術をもたないエンジニアは等しく価値がありません。 事業を推進するエンジニアにとって、特定の技術スタックにこだわらず様々な技術領域に理解があることは必要不可欠だと思っています。

いま私は、「様々な技術領域に対して、広く、かつ浅くない理解を得る」という指針を持って継続的な技術的キャッチアップを心がけています。

2.自分の給与以上の価値を生み出すコードを書く

あなたが今日書いたコードは、今日もらった給与より価値を生みますか?

これは私が先輩からかけられた質問です。

エンジニアなら誰しも、技術的に正しいことをしたいと思っています。 メンテナブルで、再利用性が高く、完結で分かりやすいコーディングを誰しもが心がけています。 また、技術的にエキサイトしたいと思っています。

しかし、自分が書いたコードが自分の給与以上の価値を生み出しているか意識しながら開発している方はどれくらいいるでしょう?

例えば営業の方々は、個人として直接売上に責任を追っています。 それくらいの当事者意識を、私は持っていませんでした。 生み出す価値は、売上でなくとも社会への影響など異なるもので構いません。

if文のネストを気にするのと同じくらい自分の書くコードの価値を考えよう、と私は意識しています。

3.スピードvs品質の二項対立に囚われない

開発を行う中で、品質に関するトレードオフが発生します。 すなわち、品質を捨ててスピードを取るべきか速度を落として品質を高めるべきか、という議論です。

業務の中で、私はどちらの選択肢も見ました。 品質に倒したプロダクトは、事業的に求められる期限を守ることができないことがありました。 スピードに倒したプロダクトは、のちに破綻して『負債』と呼ばれています。

スピードvs品質のトレードオフでは、問題は解決しないことを私は学びました。

その上で、重要なのは「守るべき品質は何か」を見極めることだと思っています。裏を返せば「捨てる品質」の見極めです。

ミッションクリティカルであったりボトルネックになりやすいと思われるところは、エンジニアの職務として徹底的に品質に倒します。 逆に要件が変わりやすかったり、作り直すのが容易であるような部分については、容赦なく品質を落とすことも必要だと思っています。

4.他職種から信頼を得られる仕事をする

さきほど、「品質を見極めて容赦なく捨てることも必要」ということを書きました。 これは関係者の協力なしにはできません。

例えば、日時の入力フォームがあった場合、ファーストリリースに間に合わせることを優先して外部ライブラリのUIを使ったとします。 これは一般にデザイナーにとって面白くありません。 サイトカラーやUI設計があって、その中に外部ライブラリの違和感あるデザインが入り込むのはエンジニアにとっても好ましくはありません。

だとしても、必要なのは「入力フォームに日時が入力できる」ことであって、きれいで独自性が高く入力しやすい日時入力フォームを提供することではありません。(その入力フォームがUX上重要な役割を担うような場合は別ですが)

この場合、チームのデザイナーの職務ややりたいことを聞き、その上で自分たちが提供するものの本質的な価値について話し合い方針を決める必要があります。

私が担当した新規機能開発の事例では、ファーストリリースではデザインを妥協していただき、ABテストでデザインをいじるタイミングで1から綺麗に作り変えました。 このように、他職種の立場にたって対話することを心がけ、信頼を勝ち取ることも事業を推進するエンジニアになる上では重要なことだと思っています。

詳しくはDevLOVEというイベントの登壇資料にまとめてありますので、もしよければ読んでみてください。

speakerdeck.com

おわりに

『事業を推進するエンジニアに求められるスキル・姿勢とは』というテーマで4つの観点を紹介しました。

少しでもみなさんの開発の役に立てば幸いです。

良いチーム作りが成果創出につながった事例

f:id:livesense-made:20170104150246j:plain

皆さんはご自分のチームが、成果を生み出し続ける「最高に良いチーム」だと思いますか?

最近よくそんなことについて考えを巡らせている、リブセンスの風間です。 ジョブセンスリンクアプリ開発チームで、ディレクター兼プロダクト・オーナー(PO)をしています。 サービスを提供するユーザーさんのこともチームメンバーのことも幸せにしたいと欲張りながら奮闘し、失敗したり喜んだりする毎日を送っています。

昨年11月22日にリブセンス社内で「アプリ大会議」が開催されました。 アプリ大会議とは、ネイティブアプリに関わるリブセンス社員が互いの知見を持ち寄り、楽しく交流を深めて仲良くなることを目的としたLT大会です。 今回は、その中で私が発表した「良いチーム作りが成果創出につながった事例」をご紹介したいと思います。

POになんてなりたくなかった

今なら胸をはって「POの仕事が楽しいです!」と言えますが、実はPO就任した当時は嫌で嫌で…。正直に打ち明けると、とても怖かったんですね。 f:id:livesense-made:20170104154738j:plain   理由は以下2つ。

  • アプリの知見が社内になく、数字を伸ばせる自信がなかったから
  • リーダーの経験がなく、チームをリードできるか不安だったから

それをどうやって良い方向に持っていくことができたか? 今回はテーマを後者の「チームビルディング」に絞って、どんな取り組みをしてきたか、それがどう成果に繋がったかをお話したいと思います。

「自分よりも優秀なメンバーたち」

当時のチームにアサインされたメンバーは、全員が年上で経験/スキル豊富な人たちでした。一方で、POの自分はアプリ社内開発も未経験なら、リーダーになるのも初めてという頼りなさ。 こんな自分が信頼してもらえるだろうか…と強く不安を感じたことを覚えています。しかし、成果をあげて目標をクリアするためにはメンバーの協力が不可欠。気持ちを切り替えて、優秀なメンバーに協力してもらえるリーダーになるためにどうしたらいいか一つずつ考えていくことにしました。

「仲間のことをすきになる」

まずは、皆のことをすきになることに決めました。そうすることで本気で相手を理解し、協力し合いやすくなると考えたからです。 やってみたのはこのあたり。

  1. 接触頻度を増やす(1on1定期開催、理由をつけてランチ等)
  2. 相手の情報を知る(すきなこと、きらいなこと等)
  3. 相手の名前を沢山呼ぶ(リアルでもチャットでも)
  4. 共通体験を増やす(納涼船に乗る/UNOで遊ぶ等)

それぞれ効果を感じましたが、中でも意外とよかったのがUNOです。チームビルディングにUNO?と思われるかもしれませんが、年齢も職種も超えて盛り上がれるUNOは互いの距離を縮めるのに効果抜群。チームの雰囲気が一気によくなって、仕事も進めやすくなりました。その後、新メンバー加入後のUNOはチームの恒例行事になっています。

f:id:livesense-made:20170104163017j:plain

「ひとりひとりの考えを理解する」

次に、メンバーのことをより深く理解するために、1人ずつじっくり話をきかせてもらう時間を作りました。 何が好きで、どんな仕事をしてる時が楽しいか、ここで何を実現させたいか…等を1つずつ尋ねていき、これまでの失敗経験なども教えてもらいます。 そして、教えてもらった内容をもとに、皆の思いを実現させつつ同時にプロダクトも伸ばせる方法がないか考え、一つずつ実行してみることに。実際にどんなことを行ったかは、次のSTEP.1~3でご説明していきます。

STEP.1 戦いにそなえる

f:id:livesense-made:20170104153459j:plain シニアエンジニアさんが一番心配していたのが、リリースを急ぎすぎたことによる今後の運用に耐えられない実装状態でした。まずは私自身が課題を把握するために、専門的な話は「例え話」を使ってもらいながら理解して、修正工数を確保。一部機能を作り直す決断もしました。その結果、改善スピードを妨げる「負」が取り除かれ、機能追加がしやすくなりました。これまであまりここに工数を割くPOがいなかったとのことで、この件はとても喜ばれ、この時に信頼関係ができはじめたように思います。

STEP.2 作戦はみんなで

f:id:livesense-made:20170104150433j:plain 企画に参加したいという声をうけ、企画案はできるだけ早い段階で皆に相談することを徹底しました。「こんなことをやりたいけどどう思う?」と手描き案を共有し、皆の知恵をもらって案を改善することで、開発着手時には「これは僕/私が一緒に考えた企画だ」と思える状態を目指します。その結果、「アプリはPOがつくるもの」→「アプリをつくるのは私たち」という意識が根付き、チームメンバー全員が自分ごと感を持って改善に取り組むようになりました。 また、企画職だけでは考えつかない優れた案がうまれやすくなる、開発側が早めに要件を把握できて開発がスムーズになる等の効果もありました。

STEP.3 見積もりは信頼してまかせる

f:id:livesense-made:20170104155559j:plain 開発方針を考えるのが楽しい、設計が好きだという意見も大切にしました。 私はよく「締切に厳しい」と言われますが、自分から締切日を指定しません。私がやるのは、この施策は何のためにやるのか、次は何が控えているか、目的とロードマップをしっかり伝えて全員に理解してもらうことだけです。いつまでにできるか/どう作るべきかはメンバーを信頼して任せ、開発方針には細かく口出ししないようにしています。(このやり方がいいかどうかは、チームのメンバー構成にもよると思います。)

たまに、そのやり方だとゆるいスケジュールを引いてラクしようとされるんじゃないかと聞かれることもありますが、実際に皆が目的を充分に理解した上で自発的に考えるスケジュールは、毎回ビックリする程スピード感のあるもの。「POに言われたから急ぐ」ではなく、「自分でやるべきだと思った基準で全力でやる」という意識がチーム内に根付いた結果、事業部内の他のチームに驚かれる早さで改善サイクルが回るようになりました。

自分ごと感をもったチームは強い!

こうしてチーム全体が前のめりになって、リリースはどんどん高速になっていき、新しい機能が次々とアプリ内に追加されるようになりました。全員で議論を重ねながら改善を重ねた施策の効果は順調に伸び、季節が変わる頃には当初のチーム目標を大きく超える成果を出すことにも成功しました。

はじめは周囲に心配されていた小さなチームでしたが、少しずつ社内で事例共有させていただく機会も持てるようになり、2016年上半期にはリブセンスベストチーム賞にノミネートして頂くまでに成長しました。 f:id:livesense-made:20170104163055j:plain

さいごに

これらの取り組みの中で、個人的にとても嬉しかった「忘れられない出来事」があります。

弊社では定期的にエンジニア向けのサーベイを実施して、開発メンバーから意見や不満を拾い上げるということをしているのですが、なんとなくそのサーベイ結果を眺めていたある日、回答の中に自分に向けられたメッセージがあることにふと気が付いたのです。

【質問項目】仕事仲間は責任をもって精一杯クオリティの高い仕事をしているか【回答】 自分がアサインした時点でかなり不利な状況を押し付けられても前向きに日々改善を繰り返しているPOは素晴らしい。正直、自分の成績のみを考えたら違う案件や部署にいったほうが正解だと感じる。そうした案件にもかかわらず、また、その分野について詳しい知識を持っていないにも関わらず、ここまでサービスを成長させた手腕と責任感はすごい。

f:id:livesense-made:20170106210954j:plain

我武者羅に走りながらも常に不安を感じていた自分にとって、これはとても心に染み入る言葉でした。

チーム全員で力を合わせて戦うことに懸命になり続けた結果、それが成果につながり、お互いへの信頼や尊敬にもつながったことを実感したこの数ヶ月。今後は、さらに大きな成果を生み続けるチームであれるよう、POとしてもっともっと成長せねばと思います。

さて、そんな私たちジョブセンスリンクアプリ開発チームですが、次に掲げた新たな夢は大きく、目標達成への道のりは険しく、会社への貢献度だってまだまだです。今日も目黒の片隅のビルで、「転職経験の乏しいユーザーにこのUIは使いやすいだろうか?」「この機能は本当にユーザーに役立つだろうか?」と真剣に議論を重ねながら、最高に使いやすい転職アプリを目指して開発をしています。もしもあなたがスマートフォンで気軽に転職活動をしてみたいなとちょうどお考えでしたら、ぜひ一度このアプリを試していただけますと大変嬉しく思います。

itunes.apple.com

play.google.com

リブセンスで働くのは面白そうかもしれないな、という考えが少し頭をよぎったあなたは、ぜひ以下よりお気軽にご連絡ください。社員一同、あなたにお会い出来ることをたのしみにお待ちしております。

recruit.livesense.co.jp

ということで… 最後まで読んでくださり、ありがとうございました。

【本発表スライドを全て見たい方はこちら】

speakerdeck.com

Livesense式 開発合宿マニュアル part1

f:id:taise:20161112151149j:plain

Analyticsグループの大政です。
普段はデータ分析基盤や、レコメンド・エンジンの開発をしています。

開発合宿、やっていますか?
Livesenseでは、仕事の一環で開発合宿をすることもあれば、有志で集まって週末に開発合宿をすることもあります。
これまで5回ほど有志で開発合宿を行ってきた経験を元に、開発合宿を成功させるためのノウハウをお話したいと思います。

今回は、(1)なぜ開発合宿をやるのか、(2)どんなスタイルがあるのか、(3)おすすめの施設はどこかについてご紹介したいと思います。

続きを読む

レガシーコードの最適化とPHPバージョンアップ

f:id:boscoworks:20161021132156p:plain

 少し前のことになりますが、正社員転職サービス「ジョブセンスリンク」を構成するPHPアプリケーション群のPHPバージョンアップ対応と、それに合わせてレガシーコードの大幅な整理を行いました。
 「PHPのバージョンあげて、リファクタリングしたんだ」と一言で言えば簡単ですが、日々のサービス改善を滞らせず、システムのリニューアルを同時に進めていくのは多大な労力を要しました。
 今回はその仕事を主に担当した、キャリア事業部技術基盤チーム*1の海野がお届けします。お手柔らかにどうぞ。

ミッション

 PHPのバージョン問題。レガシーコードの山積。システムが歳を重ねるにつれ、必ず直面する大きな問題です。
 システムは、初めてリリースされた数年前の数倍の規模になっているでしょう。
 売上を支えるシステムを維持し、事業を加速させる施策を阻むこと無く、システムのリニューアルを進める。これが今回のミッションとなりました。
 このミッションを進める上で解決したかったのは、以下の2点です。

  • PHPバージョンアップ
  • 全社共有ライブラリの最適化

 今回は、この課題に対する取り組みについてお話します。

*1:ジョブセンスリンクのインフラ管理やシステム開発を主に担当しています

続きを読む