nakarioのほぼISUCONブログ

ISUCON出るたびブログ書く

ISUCON11-priorやってみた

予選が近いので練習戦として isucon11-prior をチームでやってみました。解説記事は出ていないようだったので、答え合わせはできてませんが8割くらいは対処できたのではないでしょうか。

構成は以下のようにして、最終的に30,000点を超えるくらいのスコアで終了しました。

  • appサーバ x 2
    • AWS c5.large (2 CPU, 4GB Mem)
  • benchサーバ x 1
    • AWS c5.xlarge (4 CPU, 8GB Mem)

やったこと

  • 計測環境構築
    • 兎にも角にも計測しないことにはやることを決められないので、MySQLとnginxのログ設定を行い、golang実装にpprofからflamegraphを出力させます
    • 初期スコアはparallel=4で1,600点くらいだった気がします
  • デプロイスクリプトの用意
    • ローカルで作業したコードの変更をサーバに反映させて再起動するスクリプトを用意します
    • 実は去年まではサーバで直接作業したり一旦GitHubにpushしてサーバでpullしたりしてたのですが、他のチームに倣ってウチも導入しました
    • お手軽だし事故が減る一方、コードを一緒に見ながら議論するには一工夫必要だなと感じています
  • N+1の解消
    • MySQLのCPU負荷がネックなので、スロークエリログをもとにgetReservations、schedulesHandlerに仕込まれているN+1を解消します
    • この時点でbenchサーバの移行が完了した上で4,000かな?
  • nginxでstatic fileの配信
    • aokabiがやってくれました
    • スコアは大きくは変化しなかった(はず)
  • indexの追加
    • タイミングが分からないけど多分このあたり?
  • overbookingの解消
    • 負荷が増えてくるとcapacity以上に参加者の予約ができてしまうバグによってエラー減点が目立ってきます
    • 根本原因はcreateReservationHandler内でのtransactionにおける他のtransactionのcommit後の値の変化を考慮しないreadです
    • 取り組んでいる際にはトランザクション分離レベルをデフォルトのREPEATABLE READからREAD COMMITTEDに変更することでファジーリードを引き起こす方法で対処しましたが、後々でロックの取得後にtransactionを使わずに値をreadするだけで良かったのではと言われて「それやん!」となりました
  • schedulesHandlerの挙動をドキュメント通りに変更
    • ここらで、原因は最後までわからなかったのですがスコアが4000点付近に張り付いて動かなくなる現象が発生
    • GETリクエストばかりでPOSTが来なくなっており、得点計算かユーザの挙動に原因があると考えてドキュメントを読み漁る
    • 実装とドキュメントの齟齬を発見し、一般ユーザには空きのあるスケジュールのみを表示するように変更
    • 実装したものの点数に変化がなかったが、いつの間にか8,000点くらいになっていたので実は効果があったのかも
  • DBのmax connectionを設定
    • 点数が伸びないので場当たり的にやった
  • reservedカウントの管理オンメモリに移行
    • indexの追加とかもあったかも
    • 12,000点くらい
  • interpolateParams=true
    • 14,000点くらい
  • 2台構成に移行
    • アプリとDBで分割
    • parallel=20に変更したのもここ付近?
    • 24,000点くらい?
  • reservedのオンメモリ化をすすめる
    • 30,000点ちょい
  • (失敗)reservationのbulk insert
    • 一定間隔おきにためておいたreservationを一括でinsertする実装を追加しましたが、ベンチとの相性が悪かったのか点数は変わりありませんでした
  • (失敗?)json Encoderの置き換え
    • 公式のencoderとほぼ変わらなかった

感想

練習用に作られたものとして基本を抑えつつ、ボリュームもしっかりあってとても楽しめました!UIやパスワードまわりは大胆に手を抜きつつ、ISUCON要素をぎゅぎゅっと濃縮したような感じでした。

あたかも私がボトルネックなので変更してください!と言っているかのようにドキュメントに書いてあるID生成の部分は触ってないですし、ベンチサーバー側のメモリが溢れそうで負荷が増やせない感じだったのでまだまだ上は目指せそうです。こんなにやりがいのある問題を提供していただいて、本当に作問者の方々には感謝してもしたりないくらいです。

さて、まずは予選を突破できるよう、早寝早起きを頑張ろうと思います!