Protocol Buffers でメッセージスキーマを管理する

こんにちは!エンジニアの大槻です。

Baseconnect ではたくさんのデータを保持していますが、単一のデータベースにそれらのデータを保存し、連携する各サービスからそのデータベースにアクセスする構成には、パフォーマンスその他多くの観点から問題があります。

それらの問題を解決するため、Baseconnect では複数のサービス間でデータを同期する方針をとっています。

データの同期には Amazon SQS や Amazon KinesisApache Kafka などのメッセージングシステムを用いますが、ここで問題になるのが、メッセージングシステムを介して送受信されるデータ(メッセージ)の形式をどう管理するかという点です。

候補としては Apache Avro や JSON Schema を挙げていましたが、エルデンリングのロード中にふと「Protocol Buffers が適しているのでは」と思いついたので、息抜きに試してみました。

実装の流れ

1. スキーマを定義する

まずは Protocol Buffers を用いてメッセージスキーマを定義します。

events/example.proto

syntax = "proto3";

package events;

option go_package = "github.com/ORGANIZATION/REPOSITORY/events";

message ExampleMessage {
    string id = 1;
    int64 timestamp = 2;
    string sentence = 3;
}

2. コードを生成する

先ほど定義したメッセージスキーマGolang その他のコードから扱うため、メッセージスキーマからコードを生成します。

$ protoc \
    -I ./events \
    --go_out ./events \
    --go_opt module=github.com/ORGANIZATION/REPOSITORY/events \
    ./events/*.proto

3. Kinesis Data Streams プロデューサーを作成する

先ほど Protocol Buffers で定義したスキーマからメッセージを作成し、メッセージングシステムにメッセージを送信します。

今回はメッセージングシステムに Kinesis Data Streams を用いますが、Amazon SQS など他のメッセージングシステムでも基本的な流れは変わりません。

cmd/producer/main.go

var client *kinesis.client

// ... 省略 ...

m := &events.ExampleMesssage{
    Id:        uuid.NewString(),
    Timestamp: time.Now().Unix(),
    Sentence:  "The quick brown fox jumps over the lazy dog.",
}

d, _ := proto.Marshal(m)

r := &kinesis.PutRecordInput{
    Data:         d,
    PartitionKey: aws.String(m.Id),
    StreamName:   aws.String("STREAM_NAME"),
}

res, _ := client.PutRecord(context.TODO(), r)

// ... 省略 ...

4. Kinesis Data Streams コンシューマーを作成する

最後にメッセージングシステムからメッセージを受信したら一連の流れは完了です。

cmd/consumer/main.go

var client *kinesis.client

// ... 省略 ...

res, _ := client.GetRecords(ctx, &kinesis.GetRecordsInput{
    ShardIterator: i,
})

for _, r := range res.Records {
    m := &events.ExampleMessage{}

    proto.Unmarshal(r.Data, m)
    
    fmt.Printf("%+v", m)
}

まとめ

Protocol Buffers でスキーマを定義し、Kinesis Data Streams 経由でメッセージを送受信してみました。

今回はメッセージングシステムに Kinesis Data Streams、プログラミング言語Golang を選択しましたが、他のメッセージングシステムやプログラミング言語でもほぼ同じ流れで実装できるかと思います。

Protocol Buffers は比較的馴染みがある、複数のプログラミング言語をサポートしている、後方互換性の担保をサポートしてくれるなど、メッセージングシステムと併用するうえで非常に便利な仕組みだと感じました。

今後はもっと実践的な内容で検証していきたいと思います。

Baseconnectではエンジニアメンバーを絶賛募集中です。 もしご興味をお持ちいただけた方がいらっしゃいましたら、下記のリンクよりぜひご覧いただけますと嬉しく思います!

herp.careers

アジャイルを学ぶ「紙飛行機ワークショップ」を開催しました

こんにちは!エンジニアの富田です。Baseconnectは1つのビルをまるごとオフィスにしていて、1Fは大きなホールとなっています。

今回、この場所を使って、アジャイルについて学ぶ社内向けワークショップを開催しました。

ワークショップの内容は「各チームに分かれて紙飛行機を作ってもらい、どれだけ多くちゃんと飛ばせるか?」というものです。エンジニアを中心に8名の参加者だったので、2チームに分かれて行いました。(HRチームのエンジニア採用担当の寺尾も一緒に参加しました)


紙飛行機は以下のような作成ルールで作ります。

・ A4の紙をハサミで切って、1機につき1/4だけ使用して下さい
・ 1人が紙を連続して折るのは禁止です
・ 1度折ったら他のメンバーに紙を渡して下さい
・ 先端を丸めて下さい
・ 「飛行場」で3m以上飛んだら合格(納品)です
・ 再利用禁止
・ テスト飛行は1回につき1機だけ

また、作成は「セット」に分かれていて、それぞれの「セット」は計画・実施・検査と適応の書くフェーズがあります。

・  計画 2分
  ・ 計画後、納品数を見積もって下さい(各チームに確認します)
・ 実施 3分(飛行場で飛ばすのも込)
  ・ 実施後、納品数をカウントします(各チームに確認します)
・ 検査と適応 2分

この「セット」を4回行います。

最初に「皆さんは飛行機製造工場です。今回、より多くの納品を行えた工場が受注を獲得出来ます」というレクチャーを行いました。 単なるゲームではなく、「受注獲得のための大切な業務である」というわけです。


当日のタイムテーブルはこのような感じです。

導入・説明(10分)
ワークショップ(50分)
ダイアログ・対話(10分)
座学(20分)
ふりかえり

まずは、準備から。 「飛行場」を作ります。 手前の養生テープから飛行機を飛ばして、向こうのテーブルまで届けば合格です。

レクチャー中

みんな真剣です

投げます!

届いた!


ファシリテーターから各チームに、3セット目はルールを1つ外して良いということが知らされます。

何のルールを外すと、より効率的に合格数を上げることが出来るか、各チームで考えました。

その結果、

・ チームA:「1人で連続して折ってOK」
・ チームB:「先端を丸めなくて良い」

ということにしました。

上記の条件で3セット目は行われ、各チーム共、生産数が跳ね上がりました!

(途中からの参加者が居たため、慣れてもらうために2セット目と3セット目の間に1セット余分に行いました)

結果を見てみると、だんだんと合格数が上がっていている! 反面、あまり見積もりとの乖離がなく、大きな改善目標を持って挑戦する姿勢が薄い印象もありました。


実施後はアジャイルについて座学で学びました。

・ 繰り返し開発について
・ 経験について
・ ふりかえりについて
・ 3セット目で外したルールについて(制約)
・ ムダの話

また、作業環境を見直すことで、多少でも生産効率を伸ばすことができることが出来たのでは?という話もしました。


最後に簡単に今回のワークショップについて、ふりかえりました。

良かったこととして、下記のような事が挙がっていました。

・ 準備が出来ていた
・ いろんな人にやって欲しいと感じた
・ アジャイルの概要が分かりやすかった
・ 競争が良かった

また、もっと良く出来そうな事として下記のような事が挙がっていました。

・ 大胆なチャレンジが出来ていなかった
・ 4回目の結果で判断しても良かったのでは?
・ 抜け道を防いで欲しい
・ 回数がもっと有っても良かった
・ 要件の整理フェーズが有っても良かった
・ お互いの戦略を聞きたかった

次回開催する時は、参考にさせて頂きたいと思います。

(汚い字でスイマセン)

「もっとよく出来る」で出た中に「抜け道」というのがあるのですが、これは、参加者の一人から「紙をグチャグチャに丸めてしまって投げて良いですか?」と質問があったことです。

納品の合格ラインとしては「3m飛ばす」ということなので、「飛行機」の形状に関わらず、その点ではクリアすれば良いのですが、納品物としてはどうなのか?

作業の開始前に、どのような納品物を想定しているのか?こんなものでもいいのか?あんなものでなければいけないのか?など、すり合わせが必要だったかもしれません。 また、これは、今回のワークショップに限ったことではなく、開発業務でも必要なことかと思います。

今回の経験を踏まえて「紙飛行機ワークショップ」をまた別メンバーで開催出来ればと思います!

Baseconnectではエンジニアメンバーを絶賛募集しております! もしご興味をお持ちいただけた方がいらっしゃいましたら、下記のリンクよりぜひカジュアルにお話しさせていただけましたら嬉しく思います!

herp.careers

アルゴリズムにおけるTime Complexity (時間計算量)について

こんにちは、BaseconnectのエンジニアのEndratno Alvinです! 本日は、アルゴリズムの性能を評価するための概念を紹介したいと思います。

Time Complexity (時間計算量) とは?なぜ必要なのか?

あるアルゴリズムの速度を特定するために、実行時間を測定することはほとんどの状況において適切な方法とはなりません。なぜなら、測定結果はCPUの速度、データ量などの外的要因の影響を受けるからです。そのため、私たちには外的要因に依存せず、アルゴリズムの速度を評価する方法が必要になります。それがTime Complexity (時間計算量)です。Time Complexityは、多くの場合 Big O Notation(ビッグ オー記法)で表すことができます。

Big O Notion

概念

Big Oは、アルゴリズムが小さいサイズの入力でどれだけうまく機能するかを評価しません。 大きなデータを入れた場合に実行速度がどうなるかによって、時間計算量が変わります。

多くの場合、Big O表記法は、アルゴリズムの最悪のシナリオを表現します。 つまり、実行数(ループ数など)が一番多くの場合を考えて、それの係る時間を表しています。

係数と定数

従って、Big Oで記述するときに、実行時間の係数と定数は考慮しません。例えば、一つのデータの処理時間は5秒であっても、10秒であっても、実行時間のグラフで表す線の曲が同じである限り、時間計算量は同じです。

また、Big O を特定するために、処理を実行する前に必要な準備時間などの定数も考慮しません。なぜなら、データが大量になると全体の処理時間が長くなり、準備時間の影響が小さくなり誤差とみなせるようになるからです。

例で考える、実際に時間計算量を求めてみましょう

Linear Time Complexity (O(n))

箱を想像してみましょう。4つの箱があるとします。その4つの箱の1つに宝が入っています。他の箱には何も入っていないとします。

宝を探すには箱を開けて、確認して、宝を見つかるまで繰り返していきます。1箱を開ける必要な時間は2秒とすれば、4つの箱を開ける必要な時間は8秒です。40個の箱を開けるのに必要な時間は80秒です。箱の数が増えれば宝探しにかかる時間も増えます。

箱を開けるのに必要な時間 x 箱数

箱を開けるために必要な時間(処理時間)をOにして、箱の数(データ量)をnとすれば、このアルゴリズムの時間計算量はO(n)で表すことができます。

Quadratic Time Complexity O(n2)

他の場面を考えてみましょう。 同じく箱があって、その箱の中に1箱に宝があるとします。しかし、今回は箱をあけるために鍵が必要になります。鍵は全箱分あります。一つの鍵で一つの箱を開けられるとは限りません。

最悪の場合、すべての箱を確認する必要があります。従って、一つの宝箱に対し、全部の鍵を試すを必要があります。鍵を試すのに2秒かかるとすれば、最悪の場合、4つの箱場合は4つの鍵 x 4つの箱 x 2秒の時間が必要です。まとめると下記になります。

箱を開ける必要な時間 x 鍵の数(箱の数と同じ) x 箱の数

前と同じ方法で、Big O で表せば O(鍵数 x 箱数)なので O(n2) になります。

Constant Time Complexity O(1)

時間計算量を求めるのに慣れていただけましたでしょうか。以下は時間計算量を最小にするベストなアルゴリズムのTime Complexityを紹介したいと思います。 上記と同じ場面ですが、今回は犬を使って、宝を特定することにしました。その犬は「宝を特定する」という特別な才能を持っていることとします。

どれだけ宝箱があっても、一発で特定できる犬がいるおかげで、すぐに宝が入った宝箱を見つけることができます。

この場合、データ数に関係なく、実行時間が同じになります。この場合はO(1)と表すことができます。

Exponential Time Complexity O(kn)

もう少し応用的な使い方も紹介します。 宝箱を開けるためにn桁の暗証番号を特定する必要がある場合の時間計算量はO(kn)となります。

kは桁の進数です。nは桁数です。10進数の8桁であれば、108通りを試す必要があります。この場合は O(kn)で表すことができます。

Cubic Time Complexity O(n3)

次に、宝箱の鍵に鍵が掛かっている場合を考えましょう。プログラミングの目線で言えばループの中にループがあるい場合となり、 O(n3)で表せます。

Linearithmic Time Complexity O(n log n)

上記のO(n2)と同じようなケースですが、今回は、一つの鍵で一つの箱しか開けられないことがわかったとします。 ある鍵で箱を開けた後、その鍵は他の箱を開けられることがないため、鍵を捨てることができます。箱を開けるたびに、試す鍵が少なくなります。 従って、箱を開けるためにかかる時間が箱を開けていく毎に減少していくことになります。

上記のTime Complexityは O(n log n)で表すことができます。O(n2)よりは早いですが、O(n)より遅くなります。

Logarithmic Time Complexity O(log n)

宝箱のうちに半分を一度で探すツールがある場合は時間計算量はO(log n)になります。

まとめ

Time Complexity の「悪い」から「良い」順に並べれば、以下の順になります:

  1. O(kn)
  2. O(n3)
  3. O(n2)
  4. O(n log n)
  5. O(n)
  6. O( log n)
  7. O(1)

おわりに

開発者はより良いプログラムは誰でも書きたいと思います。プログラムを書く際に、特別な才能を持つ犬や一度でに半分を探すツールを取り入れられるかどうか、使った鍵をまた試しているかどうか、最善の時間計算量を使うことを意識することはより良いプログラムを作ることにつながると考えています。

Baseconnectではエンジニアメンバーを絶賛募集中です。 もしご興味をお持ちいただけた方がいらっしゃいましたら、下記のリンクよりぜひカジュアルにお話しさせていただけましたら嬉しく思います!

herp.careers

大学二回生がインターンとして入社し半年が経った話

初めまして、Baseconnectのエンジニアインターンの秀と申します。今回は現在大学二回生である僕が、半年間勤めて初心者ながらも気づいたことや、感じたことをお話ししようと思います。 (執筆時点で二回生、この4月で三回生になります)

はじめに

まずは、僕自身とBaseconnectのエンジニアインターンについて軽く紹介しておこうと思います。冒頭でも少し触れた通り、僕は現在大学二回生で文理混合の情報学部に通っています。

元々情報系に興味があったので、Baseconnectに入社する前から一応教本などでプログラミングの勉強はしていましたが、小さい頃からコンピューターを触っているような人間ではありませんでした。

参加したきっかけはコロナの影響が大きかったと思います。大学入学直後から講義はほとんどリモートで、出される課題は多いものの意外と自分に使える時間が沢山ありました。そんな中、見かけたのがBaseconnectのエンジニアインターン募集の記事でした。

他のサマーインターンなどと違って、期間が決められておらず最短で15ヶ月以上と長期的です。仕事に慣れてくるとリモートでの勤務も可能なので働き方には融通が効きます。僕は、ただただ課題をこなす日々を変えたくて、応募を決意しました。

その1...触れるコード量が多い

晴れてBaseconnectに入社でき、いざ初めのタスクに取り掛かるぞ!と息巻いたところ、コード量の多さに圧倒されました。ディレクトリはしっかりと階層構造で分けられていたものの、教本や映像教材でも見たことのない単語がずっしり......。最初に振られたタスクはとても簡単なものでしたが、変更箇所を探すだけでも一苦労でした。

その2...ツールの重要性

早速エンジニアとしての洗礼を受けた僕ですが、いくつかタスクをこなしたり、先輩達のありがたいアドバイスを受け、徐々に徐々にコツを掴んでいきました。その一つがズバリ検索です!!先ほど、簡単なタスクでも変更箇所を探すだけで苦労したとお話ししました。

しかしこの問題...テキストエディタの検索機能を使えば一発で解決します!!と言っても世のエンジニアの方からするとこれは当たり前の手段でわざわざ本やブログなんかに書くことでもないかと思います。

しかし、大量のコードに触れた事がなく、これまで手探りでコードを探しても困らなかった僕には無かった発想でした。この時ぐらいから今まで使っていたツールを見直し、ショートカットを覚え、真の意味でツールを使い始めました。

その3...複数人での開発

ある程度業務に慣れ、多少は周りに目を向ける余裕が出来た頃、ふと思ったのが複数人での開発はやはり個人のとは違うということです。

個人で好きなようにアプリケーションを作ってみたり、教本のコードを写経していた時というのは他人の目を気にする必要がなかったので、ファイル名・メソッド名・変数名が何であろうが自分が理解できれば関係ありませんでした。テストコードも大して書いておらず、フォーマッターやリンターなどは概念すら知らなかったです。

そんな僕だったので、Rspecをちゃんと書いたり、rubocopを通したりというのはBaseconnectに入って初めての経験でした。ですが、やはり複数人での開発を意識したコードは圧倒的に見やすく、レビューが入ることを考えても効率的です。

その4...マネジメントの意識が高い

業界の色なのでしょうか、Baseconnectに入社して一番驚いたのがこのマネジメントの意識の高さでした。僕自身昭和チックな指導スタイルの体育会系部活に長年所属していたこともあって、ちゃんとした本物のマネジメントらしいマネジメントを初めて受けて、本当に感動しました。

今、日次でデイリーミーティングを、隔週で振り返りを行っているのですが、部活をやっていた頃は怒鳴られ叫ばれは日常茶飯事でしたが、ここではそんな事は一切なく、失敗した時でも理論的に解決方法を探り、関係性の向上をモットーに改善を意識したサイクルを心掛けています。

人によっては昭和テイストのマネジメントが合う方もいると思います。しかし、僕の場合はこちらのやり方の方が確実に成長出来ていると思います。

最後に

恥ずかしながら、Baseconnectに入りたての感覚をそのまま書き綴ってみました。まだ実務を経験した事がない方には実際の様子が少しでも伝われば嬉しいです。つよつよエンジニアの方には、駆け出しのメンバーがどんなことを考えているのか少しでも伝われば嬉しいです。拙い文章の中、ここまで読んでいただきありがとうございました。

週刊データサイエンスなるデータ分析レポーティング企画をやってみた話

こんにちは。Baseconnectのオコドンです。 BI (BussinessIntelligence)ユニットに所属しており、データエンジニアとデータアナリストの両方の業務を行なっております。

今回の記事では、データアナリスト業務の中で生まれた施策である「週刊データサイエンス」なるものについて紹介したいと思います。 この施策はちょうど1年前くらいに僕が「こんな施策やりたい」と開発マネージャーにお願いして、チームの業務としてやらせてもらったものとなります。

週刊データサイエンスって?

ざっくり説明すると弊社が提供している営業活動支援サービスMusubuから取得した様々なデータを、アナリスト発信の切り口で分析して、毎週記事化する取り組みです。

どんな記事を書くの?

「◯月にリリースした新機能Aの使われ方について分析してみた」

みたいなタイトルで、分析の結果、分かったfactをTableauでグラフを作成したり、文章を書くことで表現しております。

記事テーマの決め方は色々ありますが、

  • 「たくさんの人に見てもらえるように社内でちょっと議論になっていることをテーマ化」
  • 「使ってみたい統計手法が上手く使える事例だったからテーマ化」
  • 「新機能がリリースされたからそれについてテーマ化」

などなどいろいろなパターンがありました。

記事の例

例を出した方がイメージしやすいと思うので2021/04/08刊行: メール機能が進化♪確かめるぜその真価♪の記事を紹介します。

この記事は弊社が提供しているMusubuサービスにテストメール配信機能や配信禁止リスト一覧機能が追加された直後に、速報的な形で出したものです。

  • 新しくリリースされた機能が期待通り使われているのか
  • リリースされた機能に相関がありそうな指標に影響が出ていないか

などを分析して記事にまとめました。

なぜ始めたの?

この施策は以下の4つの背景から始まっております。

データ活用意識の向上

プロダクトグロースへのデータ活用意識

プロダクトステータスをモニタリングするようなKPI作成や、自分たちの業務の最終結果であるプロダクトに対して、定量的なフィードバックを受け取る流れを作ろうとしていました。

意思決定の質の向上のためにはインプットの多角化が必要だと考えており、 仮説ベース、定性ファクトベース、定量ファクトベース、これらそれぞれのサービスステータスのインプット方法をプロダクトマネージメント層に保持してもらうためにも、定量的なサービスステータスのフィードバックを受け取る文化を作ろうと邁進しておりました。

またプロダクトグロースを担当するチーム以外にも「我々が売り出しているMusubuサービスが今どんなステータスなのか」をすぐに把握できるようにしたいと思っていました。

Rettyさんの新卒の方の記事に影響を受けて

Rettyさんの新卒アナリストの方が、毎日自身が分析したサービスステータスについてslackで一言語るという記事を見かけて、当時社内に対して定量視点での知見の共有ができていなかった僕の強い刺激になったのを覚えています。

当時のslack⬇︎ f:id:yuri_terao:20220225135718p:plain

統計技術・機械学習の試し打ちをする場の不在

当時、毎週kaggle勉強会という勉強会をチーム内で開催しており、kaggleへの参加だけではなく、効果測定の統計手法の勉強会や、統計の赤本や緑本の輪読会などを行なっておりました。

ここで勉強した手法なども、前述したプロダクトグロースに活用できていなかったので、トレーニングを兼ねていた部分もあります。

社内におけるBIユニットが実現できることの広報

  • どんなデータが現在使えるのか
  • 統計を活用したらどんなことがわかるのか

などBI領域でできることを他メンバーが把握できていないと、結果として社内からの依頼が減り、データ活用意識が下がるという負の連鎖を産んでしまうので、記事のアウトプットを通して、社内メンバーが「BIに色々頼んでみよう」と思ってもらえることが目的の一つでした。

週刊データサイエンスやってよかったこと

  • 社内にファンが出来ました
    • 事業企画室や開発チームの中に記事を楽しみにしてくれるメンバーがチラホラと出てきました。
  • より高度な仕事に繋がった
    • BIができることを広報する効果は出せたと思っており、例としては「会社データのスコアリングを作成してほしい」などの高度な仕事に繋がったと思っています。
  • 文章力・説明能力の向上
    • 読者には社内全メンバーを想定していたため、分析対象となるサービス内の特定ドメインに対する知識なんかを、記事の中でざっくり説明する能力だったり、統計の知識がないメンバーに対して「つまりこういうことがわかりました」と要約する能力がチーム内で身に付きました。

週刊データサイエンスやってうまくいかなかったこと

  • リソースが鬼のように取られる
    • 「テーマを決める➡︎データ探索・データ可視化を行う➡︎記事として仕上げる」この一連の流れはものすごいリソースが消費されて、 1人日以上は覚悟しなければならないくらいのリソース感でした。
  • 目指していたところまでの意思決定への影響は与えられなかった
    • 「明確に意思決定へ影響を与える」ことまで意識していましたが、まだそこまではいけなかったなあと思ってます。

読んでもらうために工夫したこと

  • 刊行当時はインパクトを出したかったため、毎日記事をパブリッシュしていました
    • 刊行開始した12月は1日に2つの記事を毎日書く施策を実行しました。
    • 通常業務と並行して記事を書いていたため、当時並走してくれたインターンの子と「あの時期は大変だったね」と今でも話します。
  • 共有時に一言コメントを付与
  • タイトルを興味を持ってもらえるような楽しい感じにする
  • インデックスを作成してバックナンバーが追えるようにしました

f:id:yuri_terao:20220225140305p:plain

書くために工夫したこと

依頼ベースではないレポーティング業務故にかなり書きづらいこともありました。

  • そもそもテーマ何にしたらいいかわからない
  • 決めたテーマを深掘りしても示唆が得られるかわからない
  • 結論の出し方も自分次第

BIインターンメンバーがこの課題感を言語化及び指摘してくれて コンサルの資料作成術を参考にしたフローを自発的に組んでくれたこともあり、一定この課題感の解消をしてくれました。

参考にした記事はこちら⬇︎

外資系コンサルが用いる「資料作成」という技術 | 日経クロステック(xTECH)

要するとレビューのフローを、スケルトンレビュー、ドラフトレビュー、フィックスレビューに分割する手法で

  • まずテーマだけ決める(〇〇機能についてなどのザックリしたレベル)
  • テーマに関するデータ探索を一通りする(Tableauでその機能テーマ周辺の情報をザックリ探索)
  • 探索結果とテーマをもとにどんな記事にしたいかをスケルトンレビューに出す
  • ケルトンレビュー結果から方向が定まったら記事の大枠を書く => 結論の方向性などまで
  • 大枠ができたらドラフトレビューに出す
  • ドラフトレビューが通過したら、細かい表現などを修正してフィックスレビューに出す
  • フィックスレビュー通過 => 記事として出稿

といった流れです。

週刊データサイエンスは現在どうなってるの?

当社のBIユニットは業務範囲として、ユーザー行動のログ化 - データエンジニアリング - データアナリティクスの全領域をカバーしております! 現在社員が僕1人とインターン2名という構成になっているので、データ基盤のフルリプレイスなどの業務が並行すると、どうしても記事に回すリソースが少なくなってしまいます。

結果として週刊リリースが難しくなってしまいまして、夏頃から月間データサイエンスにリネームされて、現在は毎月リリースの形を取っています。

発信はいいゾ

「なぜ始めたか」の項にさまざまな理由を羅列しましたが、一年通してやってみた感想としては データの説明、結果の解釈、サービスドメイン知識、統計、などなどを文章化して伝える技術をチーム全体で向上させられたことが何よりの価値だと思います。

アナリストのトレーニング・武者修行に是非やってみてください!

Baseconnectのデータ分析基盤変遷の歴史

挨拶

どうも!BaseconnectのBIチームに所属してます。おこどんです。 弊社BIチームは ユーザー行動のログ化 <=> データ収集・蓄積 <=> データ可視化・分析までの領域を社内で担当しております!

担当領域の都合から、クライアントサイドログ収集関連リソース, ETL, データレイク, データウェアハウス, BIツールなどなどデータ分析基盤周りのインフラリソースの作成と管理も担当してまいりました。

立ち上げから2年ちょっとの歳月が経ち構成も一旦落ち着いたので、弊社の分析基盤周りの構成の歴史・変遷を今回記事にすることとしました!

(※社員1人インターン1,2名のチームでずっと作ってきたため、人的リソース依存の課題感や技術選択があります。ベストプラクティスの参考としてではなく、失敗の歴史を温かく見守ってもらえたら幸いです)

黎明期(2020/02~) 

〜データレイクという概念の不在〜

どのような変更を加えたか

  • パフォーマンス監視及びReact製SPAのフロントログ収集を目的としてElasticAPMを導入しました。

    • APMのサービスエージェントのログにアカウント情報を載せて、バックエンド・フロントエンド共通のロギングツールとして運用しました。
      • 尖った使い方だと思うので、これは別で記事化出来たらと思ってます。
  • ETLツールのLogstashをEC2内で運用しました。

    • 弊社がストレージ用途としても活用しているElasticsearchのデータをDWHに転送しました。
    • ElasticAPMによって収集されたクライアントサイドユーザーログをElasticsearchからDWHに転送しました。
    • 弊社のアプリケーションのメインDBであるNeo4jのクエリAPIから取得したデータをDWHに転送しました。
  • ETLツールのembulkをEC2内で運用しました。

    • アプリケーションで活用しているRDS内のデータをDWHに転送しました。
  • DWHにBigQueryを採用しました。

  • BIツールにTableauを採用しました。

この構成になった理由

分析基盤の構成自体が存在しなかった状態で入社して「数ヶ月以内に何かデータが見られるようにする」ことを目標にしていました。 1人目データ人材として入社しており、データが見られるようにしないと存在価値を発揮できないと考えていた焦りと当時の経験不足故にデータレイクなんてものは存在していませんでした。

  • ETL

    • 国内では珍しいかもしれませんがfluentdではなくLogstashを採用しています。
    • 弊社はElasticsearchをストレージ目的としてもかなり活用しており、Elastic社のデザインパターンであるELK構成で推奨されているLogstashの採用をした方が、何かと良いことがありそうと考えての採用でした。
      • 現在の感想は「fluentdでもLogstashでもどっちでも良いなあ」です。
  • DWH

    • マネージドで1人体制でも管理が楽そうな点とパフォーマンスなどについて評判が良かった点から、クロスクラウド構成にはなりますが、RedshiftではなくBigQueryを選択しました。
  • ログ生成

    • バックエンド, フロントエンドの両アプリケーションのパフォーマンス監視ができるツールの検討が社内で既に行われており、ElasticAPMのreactエージェントであればページ遷移やコンポーネントのマウントまでをログ化可能なことが技術調査されていたので、その導入とカスタムログの作成などを行いました。

この構成で得られた学び

APM as ログ基盤構成について

APMツールのログにアカウント情報を付与してユーザー行動ログとして扱ってみる」というほぼ前例が無いAPMツールの使い方をしてみました。

  • フロントエンド、バックエンドで同様の形式のログが発行されて加工などが楽な点
  • ログの格納場所が統一され、パイプラインの数が1つで済む点

などなどプラスポイントもあったので、この使い方はそこまで悪くなかったのでは?と考えています。

データレイクが無いと

日ごとに取り込んだテーブルに*_YYYY_mm_ddのようなsuffixを付けて全て保存して、BigQuery内に擬似的なデータレイク層を作っていました。 dbtやdataformのようなデータモデリング技術を導入できていなかったので、BigQueryのスケジュールクエリでデータレイク=>データウェアハウスの変換を全て書いており、保守もしづらくカオスな状態でした。

データレイク作成(2020/06~)

どのような変更を加えたか

  • GoogleCloudStorageをデータレイクとして採用して、ETLのデータ輸送先をBigQueryからGCSに変更しました。

  • GCS to BigQueryの転送はCloudDataflowで行いました。

    • CloudDataflow内の定義はApacheBeam JavaSDKで記述しました。
  • CloudDataflowのジョブをキックするための関数をCloudFunctionで作成しました。

  • Cloud Functionの定期実行はCloudSchedulerからCloudPubSub経由でメッセージを投げる形で起動させました。

この構成になった理由

  • 何やらデータレイクなるものがあれば先述したBigQueryのカオスな状態が解決されるらしいとのことで、BigQueryとの親和性が高いGCSをデータレイクとして採用しました。

  • データレイク => データウェアハウスのデータ輸送はCloudDataflowで行いました。DataTransferServiceなども考慮したのですが、Transform処理(データのマスクなど)を挟むことが出来る点や動的に取得元テーブルを宣言できる点などから、Cloud Dataflowに軍配が上がった形です。

CloudComposer高すぎ問題

Cloud Dataflowの実行にCloudFunction, CloudPubSub, CloudSchedulerの3リソースの構成をわざわざ組まなくても、DataflowのマネージドサービスであるCloudComposer使えばいいじゃんと思われるかもしれません。

Cloud Composerを使わなかった理由は試験的に運用してみたらとても高かったという金銭的な理由からです。 CloudComposerの使い道が当時はデータレイク<=>DWH間の輸送の用途しかなかったため、TooRichだと感じて採用を見送りました。

この構成で得られた学び

  • やりたいことが実現できる技術 < 理解しやすい技術にしないと属人化が進む

    • DataflowをApacheBeam JavaSDKで書いたのですが、難しくて保守しづらいものにしてしまったのが失敗だと感じています。
    • PythonSDKには存在しないNestedValueProviderオブジェクトを使って、動的にパラメータを取得してコード内に反映する実装をしたいがために、pythonではなくJavaを選択しており、キャッチアップが難しい技術選択をしてしまったと感じています。
    • 導入をした僕と当時のインターンの2人だけがApacheBeamパイプラインを作れるが、後からジョインしたインターンメンバーなどはパイプラインを作れないといった状況になり、同じチーム内でも技術格差が生まれてしまいました。
  • データレイクができて感じたメリット

    • GCSに日付ごとのマスターデータを格納して、BigQuery内のデータは最新のテーブルのコピーを持つ形としたので、BigQuery UI上でのデータの一覧性が著しく上がりました。
    • マスターデータをBigQuery上で持つ形では無くなったため、元の構成に戻せる安心感を持ちつつ、立ち上げ時のぐちゃぐちゃな構成のBigQueryに対して、データセットの整理やパーティショニングなどの構成変更を行えるようになりました。
    • DataflowのETLの段階で個人情報にあたるものなどに列単位で閲覧制限をかけることで、BigQueryの権限を他者に渡しやすくなりました。

dataformの導入 (2021/01~)

どのような変更を加えたか

  • DWH内のデータモデリングツールとしてDataformを採用しました。

    • Dataformを使うことで、BigQuery内でダッシュボード表示や特定の計算を走らせるためのテーブルをデータマート層として定義しました。
  • BigQuery内の100個くらいあったスケジュールクエリを根絶しました。

  • Dataformを使うことで依存関係が明示的に示され、複雑なロジックも保守性が高い状態で書くことができるようになりました。

    • コード管理されるおかげで、SQLのレビューも徹底されるようになりました。

この構成になった理由

  • 確か当時「DataformというBigQueryを便利にするツールがGoogleに買収されて〜」みたいな話を聞いて、こんな便利なものがあるのかと感動して導入を決定したと思います。

    • 恥ずかしながらデータモデリングツールという存在をこのタイミングで初めて認知しました。
    • なんでdbtじゃないの?という疑問が湧くと思いますが、純粋にdbtをこの時知らなかったので選択肢にも上がりませんでした。
  • スケジュールクエリでのDWH内データ変換が地獄すぎた。

    • スケジュールクエリは一覧性が悪く、管理もしづらく悩みの種でした。

この構成で得られた学び

  • データモデリングはBIの最重要業務。良いこと尽くし

    • 複雑な定義のKPIなどのテーブルも、テーブルやViewに分割することで理解及びレビューをしやすくなる。
    • 更新タイミング、Table化、View化などの管理すべき項目が全て定義可能。
    • テストを書くことで、データ欠落やロジックの意図せぬ変更などを補足可能。
    • テストユーザー除外処理やタイムゾーン変更処理などの共通する処理を作ることで、今後の開発の高速化に繋げられる。
  • dbtでもdataformでもどっちでも良さそう

    • 1年以上dataformのSQLX書きまくってますが困ってないので、どっちでもやりたいことできるんだろうなあと思ってます。
    • ただdbtのユーザーコミュニティの盛り上がりは羨ましかったです

事件:Neo4jがREST APIを廃止 (2021/06~)

アプリケーション開発の都合から、弊社アプリケーションのメインDBであるNeo4jがver4.0に更新されたのですが、この更新によってboltプロトコルによる通信のみが許可される形となり これまで活用していたREST APIが使えなくなることになりました。

手持ちのETLツールであるembulkやLogstashなどではboltプロトコルによるNeo4jからのデータ取得をサポートしてくれるようなものは存在せず、既存のETLツール以外の何らかのデータ取得手段を作成する必要が発生してしまいました。

データレイクお引っ越し・分散処理・インフラのコード管理(2021/09~)

どのような変更を加えたか

  • AWS内でBIのデータエンジニアリングに関するリソースを別アカウントに切り出しました。
  • Terraformによる全BIリソースのコード管理を実施しました。

    • IAM, ネットワーク, ETL, データレイクなどのコード管理をしました。
  • ETLツールをAWS Glueに一本化しました。

    • Neo4j ApacheSpark connectorを使うことで、Neo4jからのデータ取得を可能としました。
    • GlueのSpark定義ファイルはScalaで記述する方針としました。
  • データレイクをGCSからS3に変更しました。

この構成になった理由

  • BIリソースの別アカウントへの切り出し

    • これはBI発信ではなくSREの方のAWSアカウント設計に則ってリソースを引っ越しました。
    • この辺りのAWSアカウント設計周りなどは SREの方が記事化してくれると願っています。
  • Terraformによるコード管理

    • 長年連れ添ったインターンの子が退職することとなり、BIリソースについて知識を持っているメンバーが僕だけになってしまったので、属人化とリソース枯渇が顕著な問題になってしまいました。
    • また、インフラに強みがあるわけでも無いため、社内メンバーから僕がインフラを触ることに対する不安の声が結構上がっていました。
    • そこでアカウント分割を機にコード管理をすることで、属人化の解消、インフラリソースの透明化、BI業務の安全性の担保を行いました。
  • ETLとしてGlueを採用

    • Neo4jからのデータ取得が可能なドライバーがApacheSparkくらいでしか見つけることができず、ApacheSparkを動作させられる環境が必須要件でした。
    • 管理するコストはできるだけ少なくしたいため、フルマネージドなサービスを検討しました。
    • ETLツールは複数あるとキャッチアップコストや管理コストがかかると考え、 ETLを全てGlueに統一することにしました。
      • ApacheSparkが動作環境になるので、ほぼ全てのデータソースへの接続が可能となりました。
    • ETL処理の分散処理化
      • データが大きすぎてETLが動かなくなるといった事故が時々起きていたのですが、スケーラブルな分散処理にすることで防止しようと考えました。
    • pysparkだとできないことがあったり、Scalaを触ってみたかったり、pythonだとDataframeの変換の時にパフォーマンスが良くないらしいとの噂を聞いたのでScalaでコードを書く方針とした。
  • データカタログの作成

    • データレイクに格納されたデータはGlueCrawlerによってカタログテーブルに登録する方式としました。
    • カタログテーブルを指定してデータ輸送ができるので、Glueのデザインパターンに寄せたコードを書くことができるようになります。
  • データレイクをS3に移行

    • これまでは「データレイクとは分析のための生データを保存する場所」という考え方だったのですが、より役割を拡張して「データレイクとはアプリケーションの種々の生データを保存する場所」としました。
    • サービスが稼働しているAWS環境のS3に変更することで、AWSマネージドなデータ輸送の仕組みが活用でき、上記のようなデータレイクの実現が容易になると考えました。

この構成で得られた学び

  • Glue高い

    • AWSはDPU (DataProcessingUnit) の起動時間に比例して課金されます。
    • プロセスの立ち上がりにも結構時間がかかるので、小さいボリュームのデータ輸送であっても、立ち上がり時間などを考慮すると結構な金額が発生することになってしまいます。
    • マネージドサービスなので覚悟はしていましたが、Logstashやembulkの維持費と比較するとかなり高額なため、ワーカー数のチューニングや取り込み回数の見直しなどの考慮点が新しくできました。
  • Spark難しい

    • RDD, DataFrame, DynamicFrameなど、Glue上で扱えるデータオブジェクトの種類が色々あって理解が最初難しい。
    • Dataflowの時の反省を生かさずに、pythonではなくScalaで書いてしまったため、キャッチアップのハードルがpythonと比較して結構上がってしまったなあと反省しています。
    • 静的型付け言語なので、「大規模データ基盤を安定したものにしたい」意図には沿っているかなと思ってます。
  • ETLツールを1つに統一したことに意味はあったのか

    • ETLという役割を複数ツールで実行するのではなく、スケーラブルでマネージドな1つのリソースにまとめたら無敵なのでは?と考えたのですが、先述した料金の問題などを考えるとそこまでのメリットを感じられていないのが現状です。
    • 管理コストというか意識するべきことが減ったので、少人数でも基盤の運用はしやすくなったことは明確なメリットとして感じています。
  • Terraform鬼便利

    • 導入目的として挙げていた、「属人化の解消」「インフラリソースの透明化」「BI業務の安全性の担保」は全てリソースのTerraform化によって解消されたと考えています。
    • モジュール化などリファクタリングすべきことはまだまだありますが、同一リソースの作成などは思考リソースほぼ使わずに実装できるようになりました!

Lookerの導入 ( 2021/12 ~ )

どのような変更を加えたか

  • BIツールをTableauからLookerに変更しました。

この構成になった理由

  • データ基盤が一定整ってきたが、ビジネスサイドのメンバーでSQLを叩けるメンバーはおらず、データ活用をしているとは全く言えない状態でした。

    • ダッシュボードや分析レポートなどは全てBIチームが出力している状態でした。
  • いざビジネスサイドに活用してもらおうと考えても「BigQueryデータの整理」「データにラベリング」「テーブルの関係性の説明」「SQL講習の実施」など途方もない道のりでした。

  • Lookerによるデータラベリングと探索環境の提供によって、これまでできなかったデータ活用を推進できると考えました。

この構成で得られた学び

  • Lookerの圧倒的なビジネスインパク

    • Tableauを使用している時は「使えるようになりたい」と名乗り上げるメンバーも現れなかったのですが、Lookerでの日本語ラベリングされたデータと探索環境を紹介することで、データ探索希望者が複数人出てきました。
    • これまでどんなアウトプットであれBIチームが手を動かしていたのですが、LookMLを作れば作るほど、データ探索者が自身でアウトプットできる環境が整うため、BIがより本質的な業務に集中できるようになりました。
    • 実際にデータを触ってもらうことで、「こんなものも見れるようにならないか」とBI以外のメンバー発信による環境作成依頼が来るようになりました。
  • Looker導入の工数

    • Looker定義用ファイルであるLookMLを書いていくのに時間がかかると考えていたのですが、そこまで時間はかかりませんでした。
      • 事前にDataformを活用することで、データモデリングをある程度のレベルまで行えていたからだと思います。
  • LookMLは考えることがいっぱい

    • 一通り作ることができたのですが、適切な権限設計、キャッシュとスケジューリング、テンプレートフィルタやリキッドフィルターなど、データ活用者がより便利に使えるようにするために、考慮したりやることが山積みです。
    • LookMLと Dataformの責任分界点、「どこまでをどっちでデータモデリングするか問題」は永遠のテーマ感があります。

まとめ

弊社データ基盤のNext To Do

  • データ発生からデータ閲覧可能になるまでの時間の短縮

    • データ基盤のSLIを「データが見られるようになるまでの時間」と定義づけるならば、その短縮に対するアクションはほとんど打てていない状態です。
      • 直近だとデータ取り込みジョブのイベントをフックにして次のイベントを起動するような構成を実装中ですが、データモデリング層やダッシュボード表示までを含めた部分は、改善どころか実態把握からのスタートになりそうです。
  • リバースETL

    • BIチームでは、弊社内で製造したデータを統計的に評価するモデルなんかも作成したりしています。 モデルの評価結果なんかをサービスに還元するようなリバース ETLのような機能の立案と構成作成には挑戦してみたいです。
  • データガバナンス

    • 「誰がどのデータを見られるべきか」といった権限設計は作り切れておらず、どのメンバーが見ても問題がないデータのみを提供している状態です。
    • データガバナンスの設計をしっかりとして、アクセスするべき人が自らの意思決定のために必要なデータにアクセスできるような、権限管理の設計は詰めていきたいです。

BIはいいゾ

今回の記事で紹介した通り、BIという領域に絞っただけでも GCP/AWSの基礎的なリソース, SQL, ApacheBeam(Java), ApacheSpark(Scala), Dataform, Terraform, LookMLなどの様々な技術が弊社内では使われています。 最近ホットな領域であるため、新しくやるべきことが次から次に出てきて楽しいです。 読者の方々もこれを機にBIのエンジニアリング部分に興味を持ってみてはいかがでしょうか?

(まだまだやりたいことはありますが、リソース的に限界なので、興味ある方は是非採用ページから応募してください)

herp.careers

Regional Scrum Gathering Tokyo 2022に参加しました!

こんにちは、エンジニアの富田です!

2022年1月5日〜1月7日まで開催されたRegional Scrum Gathering℠ Tokyo 2022に参加してきました!

twitter #RSGT2022 https://twitter.com/hashtag/RSGT2022https://twitter.com/hashtag/RSGT2022twitter.com

[Regional Scrum Gathering Tokyo 2022のスライドまとめ #RSGT2022

scrummasudar.hatenablog.com


Regional Scrum Gathering Tokyo(RSGT)とは?

「Regional Scrum Gathering Tokyo」は、日本最大級のアジャイル関連のカンファレンスです。 毎年、1月上旬に東京で開催されます。

去年はオンラインで参加したのですが、今回は会社から参加費を出してもらい、現地参加しました。

コロナ禍でオフラインの集まりにほとんど参加していなかったのですが、久しぶりに大勢の人と話すことが出来、3日間、どっぷりとアジャイルの世界に浸かることが出来ました。

また、オンラインの参加者はDiscordで活発にやりとりされていたのですが、そちらを見て感想を楽しんだり、投稿内容から知識を得ることもできました。


参加してみてどうだったか?

一番、印象に残っているのは、プロダクト・スプリントのそれぞれのゴールの話でした。

現在、私のチームではスクラムで開発を行っているのですが、スプリントゴールがあいまいになりがちでした。

スプリントゴールは、プロダクトゴールから逆算して、直近(現在のスプリント)で実現すべきものかなと思います。

プロダクトゴールがぼやけてしまっているのが、スプリントゴールにも波及していることが理解出来、帰ってきてからプロダクトオーナーとこの点を話しました。

また、システムコーチングを体感するワークショップにも参加しました。 オフラインのワークショップも久しぶりなので、かなり緊張しましたが、楽しく実体験として学ぶことが出来ました。


参加後

参加後は、レポートを作成して社内に公開したり「共有会」を開催しました。 「共有会」はレポートを元に、1日目から順に登壇の内容や感じたことをを報告していきました。

RSGTの3日目は、毎回Open Space Technology(OST)が開催されるのですが、その動画を見ながらどんな風に開催されるのか共有しました。

社内では、まだアジャイル開発が広まっているわけではないので、上記のような活動で少しずつでもアジャイルのファンを広めていこうと企んでいます 😎

来年は、社内の他の人も巻き込んで参加出来ればと思っています!


ちなみに、参加中、東京は、歴史的な雪景色でした。

Baseconnectではエンジニアメンバーを絶賛募集しております! もしご興味をお持ちいただけた方がいらっしゃいましたら、下記のリンクよりぜひカジュアルにお話しさせていただけましたら嬉しく思います!

herp.careers