ISUCON12に参加して、総合14位で本選進出することになりました🎉

こんにちは!バックエンドエンジニアのうつみです。

7/23(土)に開催されたISUCON12の予選にチーム「パカパカアルパカ」として参加してきました!

参加メンバーは

となります。

TVerTechnologies時代から何度かこのメンバーで挑戦していたのですが、いつも30位ちょいとかのあと一歩及ばずみたいな結果でした。

しかし今回は無事予選通過できました🎉🎉🎉🎉🎉🎉🎉🎉

ちなみに去年のISUCON11からTVerは協賛させていただいており、今回ももちろん協賛させていただいております!

techblog.tver.co.jp

本選参加者へのみなさまには、今年もTVerから当日慌ただしい中でも糖分や元気を補充していただけるようなワンハンドスナックなどのお菓子をお送りさせていただきますのでお楽しみに!!!!

当日のこと

お題

今回はisuportsという、eスポーツ向けSaaSが題材となっておりました。

今までのISUCONではMySQLにデータが乗っていることが多かったのですが、今回はなんとマルチテナント化をSQLiteのファイルをわけるという実装になっておりました。

開始30分

元々何度か素振りをしていたので開始30分でやることは

  • レギュレーションをしっかり読み込む
  • いつものスクリプトを用意する
  • どんなものが動いているのか全体像を把握する

と決めていました。 ISUCON11のレギュレーションはとても複雑だったので、今回も同等のものがくると覚悟していたのですが、思いの外シンプルだったので全体像の把握に努めました。

方針

今回はデータの書き込みがエンドユーザーから頻繁に発生するようなアプリケーションではなく、入稿されたタイミングがほとんどを占めていたので

如何にリードをDBに向かせないか。というRedis大好き発想でいろんなデータをRedis化していくことにしました。

では時系列とスコアでどのようになっていたかの記録を書いていきます(SlackとGit logから拾い直しているので抜け漏れはたくさんあります。

時系列スコアと実装

グラフ

10:56 (初期スコア

3165

11時ごろまで SQLiteマルチテナントかよ・・・どうすっぺよ・・・ と途方にくれていました。

11:30

2862

  • pprof
  • SQLiteのクエリログ
  • MySQLのスローログ
  • jwt認証時に毎回pemファイル読み込んでいたものをアプリ起動時のみに変更

色々ツール入れたりしてたので初期スコアよりさがりましたね。まだ慌てなくていい。想定内です。

12:00

2741

  • initializeでテナント情報をGoのオンメモリキャッシュに持つように変更

13:00

6627

  • id採番をMySQLからRedisのIncrに変更
  • initializeでvisit_historyをRedisに持たせる実装
  • player_socreにIndex追加

やっと初期スコアを越してきました。 まだまだこれから

13:30

10341

  • flock周りを解消
  • 大会情報をオンメモリ化

大台きました!

恐らくですが、flockはそのまま外すだけではダメだったのですが並行して行っていたRedisからの読み込みに変更していた部分などとええ塩梅に絡まって単純に外すだけでスコアが伸びました!やった!

なお、このときのひどいコミットログはこちらです

きっとキャッシュって入れたかったんだと思うんですよね。

キャン酒・・・ Can 酒

そろそろお酒が欲しくなってくる頃合いだったのでしょうか🤔

14:00

11575

  • テナントごとに大会情報のキャッシュしてたけどFailするので削除
  • flockをどんどん解消

14:30

13042

  • RankingでのN+1を解消

着実にあがってきています。いい感じですね。

14:00頃から私はplayer_scoreのRedis化をゴリゴリ実装していたのですが…

15:30頃までバグが取れませんでした…

なので、一度気持ちを切り替えて別のチューニングをやることにしました。

ISUCONは限られた時間内で山程ある課題を潰していかなければならないため、手戻りやロスはできるだけ減らしたいところです。

意地にならず、諦めを早めにつけて別のアプローチを探すことも一つの手です(1h30mも溶かした人間がいうことではない

15:30

14914

  • テナント作成時にSQLiteにIndex追加するように変更
  • player情報をオンメモリキャッシュに

もうここからは最後の追い込みだったので、Slackではなく音声会話だけになってしまいlogがあまり残っていませんでした…

17:05

24445

  • player_scoreの最終値だけをRedis化
  • add系APIによるSQLiteへの書き込みをBulkInsert化

17:20

30978

  • ranking内によるplayerテーブルとplayer_scoreのテーブルのJOINを解消

3万きた!

一旦ここでチャレンジはやめて、レギュレーションの再チェックなどを行いました。

17:30

35383

  • アプリケーションログOFF
  • MySQL スローログOFF
  • SQLiteクエリログOFF
  • nginxログOFF

うおぉぉぉぉ!ってなりました。 これが我々のBESTスコアになります。

17:59 提出スコア

30616

再起動テストを行ったりすると、なぜかFailしてしまい最後の最後で慌てていました。

でもなぜかログを有効に戻すとFailしない…。

これが古より伝わる おまじない ってコメントついてるやつなのね…。という気持ちになりながらここは安全に倒しました。

アルパカ大明神によるブログ

アルパカ大明神視点でもブログを書いてくださっていますので是非ご覧ください〜〜

toritori0318.hatenadiary.jp

最後に

TVerでは地上波連動や、スポーツ番組延長による枠切れなどで国内でも珍しい超短期型のアクセススパイクなどが日常的に発生しています。

安定してコンテンツをユーザーさんに届けるため我々バックエンドチームは日々改善を続けております。

ISUCONを楽しめるエンジニアのみなさんならきっとTVerのスパイクも楽しんでいただけるのではないでしょうか。

我々はまだ発足1年ちょっとの小さな開発組織です。

これからどんどん大きくしていきたいと思っておりますので、ご興味ある方は是非お声がけくださいませ。

www.wantedly.com