注目キーワード
  1. react
  2. docker
  3. インターン

新卒でDSPを作るということ

  • 2020.07.18
  • 雑記
  • 1195回
  • 0件

新卒の配属でDSPを開発する部署に配属となり2ヶ月がたったので、技術的に成長できてる点(今後出来そうな点)や技術以外の点で勉強になっている点をまとめてみたいと思います。現在のプロダクトに特有のことというよりかはDSPでの開発という一般論的なところについての内容にするつもりです。

DSPとは

DSPとはDemand Side Platformといって広告を打ちたい企業から予算とクリエイティブをもらって、最適な配信を行うシステムのことです。DSPの対になるものとしてSSP(Supply Side Platform)があります。これはメディア側の配信を最適化するためのシステムです。

SSPはメディアの広告枠を買い付けて表示(imp)されるごとに提携しているDSPに対してユーザー情報などを送信し、その枠をいくらで買い取って広告を表示させるかのリアルタイムオークションが行われます。これがRTB(Real Time Bidding)と呼ばれるものです。

このあたりは調べてみるとたくさんの紹介記事が出てくるのでここではこれぐらいにしておきます。

 

技術的な成長ポイント

配属されて2ヶ月ちょっとですが、正直めちゃくちゃ技術的に成長できていると思います。

パフォーマンス要件

DSPのパフォーマンス要件はとてもシビアです。普段webサイトをみたときにページを読み込んでから広告が表示されるまでにどれぐらいの時間がかかっているでしょうか?電波状況にもよりますが、だいたい1秒〜数秒ぐらいですよね。

それもメディアが読み込まれてからしか広告のリクエストは飛ばないので、実際には広告枠がレンダリングされてから広告が表示されるまでに1秒もかけられないことになります。その間にDSPとSSPの間でRTBが行われるので、RTBにかけられる時間はわずか数百msということになります。SSP側での処理やバッファも考えるとDSP側の猶予は最大でも200msぐらいといったところでしょうか?

つまり数十msの中でそのユーザーに最適な広告と入札価格を決定する必要があります。100ユーザーぐらいだけを専門に広告を配信するなら余裕かもしれませんが、それでは利益がほとんどでないので合計の配信ユーザー数はどのDSPでも数千人オーダーになっています。

 

この要件を満たすためのキャッシュ戦略やデータの持ち方などはとても考えることが多いです。単にキャッシュしまくるだけではredisへのアクセスが増えてCPUが張り付いてしまい逆にレイテンシーが上がったり、データストアに予め計算してbulk insertをしておくにはデータ件数が現実的でなくてそのデータストアが落ちたり、落ちなくてもめちゃくちゃお金かかったりということがすぐに起こってしまいます。

大規模トラフィックでかつ大量のデータを扱う必要がある状況下でいかにパフォーマンスを出すのかという課題が今まで経験したことがなくとても勉強になっています。

トラフィック

DSPはかなりのリクエスト数があります。というのもいろいろなSSPに接続していてさらにその先に多くのメディアがつながっているからです。またひとつのページに複数の広告枠が存在しているので、1 impだけでも2〜10 RTBが行われることになります。

接続するSSPの数やスペックにもよりますが、だいたい数万〜数百万 req/s ぐらいの規模感です。

だいたいこんな感じのことが日本中、世界中で毎秒毎秒大量に起きています。実際にはもっと複雑になっているはずです。

ただしリクエスト数がスパイクすることはないので、スケーリングについて深く考える必要がないのは他のサービスとは違ったところかもしれません。ピーク時はあるものの毎日だいたい同じ傾向です。

とはいえこの規模のサービスに触れる機会は今までなかったので日々これぐらいのリクエスト数がくる環境で開発できるのはとても勉強になります。

大量のデータ

大規模なデータというとデータサイエンティストや機械学習な人たちが頑張るものという印象が強いと思いますが(というか自分がそうだった)、そもそも大規模なデータを処理したり保管するだけで難しいしお金もかかります。計算量やメモリを意識したコーディングをしないと死にます。

というか死にました。100万行ぐらいのテキストファイルをパースする必要があったのですが、それを一行ずつ処理して成功なら成功Listに追加して失敗なら失敗Listに追加するという実装をしました。ScalaのListはLinkedListで末尾追加はO(N)です。そのため全体としてはO(N^2)ぐらいの計算量になって爆死しました。

ログも大量ですぐにテラバイト級にまで膨れ上がります。fluentdでログを流すにしても多すぎて詰まったり反映が遅れたりということは起きやすい状況です。

課金周り

DSPではほとんどのことがお金の流れに関わってきます。だいたい半分ぐらいの実装がお金の流れに関わる部分な気がします。今までしっかりテストを書いた経験はなかったのですが、DSPを作るようになってからテストをどうしても書きたいという気持ちに切り替わりました。それぐらい複雑で簡単に壊れます。w

間違って1000をかけたり間違って10で割ったりするとそれで終わりです。あと初期値の選択もめちゃくちゃ慎重になる必要があります。(たぶんこのあたりは全部1回は配属後やらかけてる気がする。。)

「いやいや間違わんやろw」って思うでしょ?間違えるんですよね〜。というのもクリック課金だったら1000 impあたりの料金(CPM, Cost Per Mill)で、クリックなら1 clickあたりの値段(CPC)でみたいな仕様があったりします。あと設計ミスで確率を予測した値がなぜか百分率ではなくパーセントで入っているなんていう技術的負債があったりします。

 

たとえば、クリック率の予測値(予測CTR)が0.2 % であると計算されたとしましょう。このときの1000 impあたりの売り上げの期待値はCPC(クリックされたときの請求額)× 予測 CTR × 10 です。まあ間違えかねませんよね。これを間違えると超高額請求の悪徳DSPか超赤字のガバガバDSPになってしまいます。これぐらいややこしいけどシビアな実装がそこら中にあります。

ちなみに僕はdev環境でCPMを14万円にするDSPをつい先日作ってしまいました。(本番ではないので全く問題のないただの笑い話ですみましたが)

技術的負債との戦い

これぐらいやべぇシステムに負債がないことなんてレアでしょう。。今のプロダクトでは日々負債と戦っています。

 

ただ、新卒のうちに負債を経験できているのはむしろ幸運なことだと思っています。なぜなら人は痛い目に遭わないと学習しない生き物だからです。

単にコードやデータ構造の負債から大規模データの管理の負債などなかなか経験することができなさそうなところまでいろいろ

技術以外の成長

ビジネス面

正直ビジネスのことを理解していないと実装できませんし、そもそもエンジニアしか考えられない仕様というのも多くあるのでけっこうビジネスに踏み入った開発になります。そもそもアドテクの全体像をしっかりと理解していないと読めないコードがけっこうあります。(ベストなのはコードを読めばアドテクのことも理解できる状態ですが、まぁそんなプロダクト存在しないでしょう。)

今のプロダクトに関していうと毎週のMTGではお互いに議論する場があり新卒でありながらも一緒に作っていっている感はめちゃくちゃあります。

 

また、広告主側のビジネスについても理解する必要がありこれもついでに勉強できてとても楽しいです。

今のプロダクトはリテール系のDSPなのでリテールや今流行のDX系はちょっとずつ勉強していってます。技術だけをやりたい人はここまでやる必要はないかもしれませんが知ってるにこしたことはありません。

データサイエンス/ML

データサイエンスやMLチームとの距離が近いのはけっこう特徴だと思います。DSチームが解析したものを元に作ったモデルである値を計算して、それを使って入札価格を最適化するといったことは日常茶飯事でお互いの連携がとても重要になってきます。また、おもしろいデータがとても身近にあるのでどこにどんなデータがあるのかを把握するためにDSの人たちに教えてもらってRedshiftにあるデータをtableauで可視化するなんてことを遊びでやったりもしています。

つい先日は新卒だけでABテストを実施して評価をするということもしました。これによってDSが普段どのようなことを考えてどのようなタスクをこなしているのか、がちでやろうとしたらいかにABテストが難しいのかといったことを学ぶことができました。

 

MLOpsをやっているのを直近で見れたりもするのでML/DSに理解のあるサーバーサイドエンジニアぐらいにはなれてきてる気がしています。

何が言いたいかって?

そもそもDSPは技術的にもビジネス的にもめっちゃおもろいし、新卒のときにこれを経験できてるのは後々めちゃくちゃ役に立つだろうなって話でした。

そういや2ヶ月前はscalaどころかサーバーサイドも初心者でした。scalaでいきなりサーバーを書くのが可愛く見えるぐらいハードで刺激的な日々でしたね。ここはけっこうなんとでもなりました。