ISUCON12の本選にパカパカアルパカとして出場し、Failしてとても悔しい思いをしてきました!

どうもこんばんは!

バックエンドのリードエンジニアをやっているうつみです。

8/27(土)に開催されたISUCON12の本選にチーム:パカパカアルパカとして参加してきたのでその感想を書いていこうと思います。

タイトルにも書きましたが、結果は残念なことに Fail でした!

今回のテーマは?

今回の問題はソシャゲでした!

私は前職がソシャゲの会社でバックエンドをやっていたので出題の動画を見たときに謎のプレッシャーを感じていましたw

でも、前職でも色々チューニングはしてきたのでやってやるぞ!という気持ちで頑張りました。

Failの原因は?

追試で失格になってしまったようです。

私がオンメモリキャッシュ大好き人間なので、masterデータをキャッシュしていたのですが分散したAPIサーバーへのキャッシュパージリクエストがうまく受け取れていなかったことが原因でした。

なので、ベンチマーカーが二回目走行しようとすると、前回の走行によって更新されたデータが一部のAPIサーバーで残ってしまっており整合性チェックでFailとなってしまいました。

ちなみにスコアなどのレポートはこちらです。

isucon.net

記憶が曖昧なので、タイムラインで追いかけるのはやめて我々のチームが行った修正についてざっくり書いていこうと思います

Redisの導入

これは予選でも行っていたんですが、初期実装でMySQL側でID生成を行っていた実装をRedisに載せ換えました。

MySQLのAutoIncrementにするかも検討したのですが、今後どこまでMySQLを剥がせるかわからなかったため、初手ではRedisを選択しました。

また、Session系もRedisに置き換えました。

コードを読んでいるとDeletedAtにデータを追記している論理削除方式が取られていましたが、DeletedAt != nil の状態はすべてInvalidSessionとして扱われることがわかったので Redisのキーごと削除する方針を選択しました。

MySQL側のチューニング

こちらは一般的なIndexを張る作業を粛々とこなしてくれていたメンバーがいたので順調にスコアが伸びていきました。 この時点でおよそ4万点ほど出ていたような気がします。

また今回の初期実装で唯一JOINされていたカード情報の取得の部分も、masterデータとのJOINを剥がして計算量を軽減させました。

分散構成

今回はサーバー5台の問題だったので

  • app1: apiサーバー
  • app2: apiサーバー
  • app3: Redis
  • app4: MySQL(ユーザーデータ
  • app5: MySQL(master系

という構成でのフィニッシュとなりました。

やりたかったこと、できなかったこと

ISUCONは時間をかければいっぱい解決方法は思いつくのですが、実際はそれらを

  • 何をやるのか
  • どのくらいの時間をかけてやるのか
  • 何をあきらめるのか

を瞬時に判断しながら進めていかなければなりません。

ユーザーデータ系のsharding

ほんとはめちゃくちゃやりたかったんですが、クエリの種別の判断や、実装インパクトで少し日和ってしまいました。

どう考えてもライトヘビーだったのでできるなら時間内にやりきりたかったです。

感想

ほんとに楽しい問題でした!

今まで何度か参加させていただいていますが、本当に毎回全力で楽しませて頂いております。

エンジニアとして、8時間他のことを一切考えずに目の前の課題にチームで挑むのは本当にいい刺激にもなりますし、勉強にもなります。

我々TVerでは日々ISUCONのような負荷対策が必要なサービスを複数展開しているため、実業務でもとてもいい影響があると思っています。 まだまだ技術組織としては小さい我々ですが、数年以内にはTVerのバックエンドチームが複数本選の常連になれるような組織を目指していきたいと思います。

ご興味ある方は是非お声がけくださいませ。 採用ページ

延長戦

ブログを書いている間に、ドワンゴ様、LINE様の粋な計らいにより、本選環境をそのまま利用させていただくことができました🎉

色々悔しかったので、一人こっそり延長戦をしてきました!

すると、なんということでしょう!!!!!

284091!!!!!!

284091

にじゅうはちまんてん!!!!!!!

2位じゃん!!!!!!!!!!!!!!!!!!って一人でホテルで枕をブンブンしてましたw

ちなみに延長戦で私がやったことを書いておきます

バグ潰し(20minほど

キャッシュパージリクエストがapp2のNginx側でルーティングされておらず、adminAPIでのマスターデータ更新時のキャッシュパージがapp2だけうまくできていませんでした。

そのため、app2へのリクエストはすべて statusCode:422, "invalid master version" となってしまっておりました。

更に422のエラーは通常でも起こり得るエラーなので、失敗や減点対象となっていませんでした。

そのため気づくのがかなり遅れてしまったのが敗因です…。悔しい。

422が大量に返却されることにより、マスターデータ更新後は 減点はされないが加点もされない という状況になっていたと思われます。

また、冒頭に書いていたFailの原因でもある、ベンチ走行時の初期化処理で前回走行のデータを正常に削除するようにもしました。

ユーザーデータ系のsharding(15minほど

masterデータはすべてオンメモリに乗せていたので、ユーザーデータのshardingをやってみました。

幸いなことに今回の問題では、複数ユーザーを跨いだデータ取得はなかったので、何も考えずにUserIDで接続先のDBを分岐するように変更しました。

その時の構成としては

という形にしました。

ほんの少しの修正でこんなにもスコアが伸びるというとても悔しい思いをしました。

が、それもISUCON。むしろそれがISUCON。

8時間という決められた時間の中で、正しく早く適切に修正を求められる環境では延長戦のときのように落ち着いて思慮できたか?と言われれば難しいかもしれません。

この悔しさをバネに来年、パカパカアルパカは優勝を目指して再度参加させていただきたいと思います!

さいごに

ISUCON運営のみなさま、出題のみなさま、インフラ提供のみなさま、我々と戦ってくれた参加者のみなさま。 本当に楽しい時間をありがとうございました!