この記事は2021夏のブログリレー17日目の記事となります。たぶん。
今回はISUCON11予選の参加記となります。
ISUCONってなに
ISUCONはIikanjini Speed Up CONtestの略で、おもいWebアプリを渡されるのでいい感じに速くしていくというコンテストです。ISUCONではベンチマークという現実の数万倍のアクセスを仮想的に行い、それに対して正しく返せるかどうかでスコアを計算し、そのスコアを用いてチーム同士で競い合います。単に高速化すると言っても触る範囲は広く、アプリやリバースプロキシ、データベース、ネットワークなどなど総合的な知見やノウハウを必要とする競技です。
チーム
私と@yukikurage、@yujiの3人でチーム名「特になく」で出場しました。全員ISUCON初参加でした。
事前にしたこと
PISCONというtraP内でISUCONの過去問を解くコンテストに参加しました。今年はISUCON9予選とISUCON10予選の問題を使いました。私の方は1日中PISCONしたりとかなり楽しませて頂きました。
↓PISCONのスコアグラフです。色んなボトルネックを解消して溜まった改善が一気に得点が繋がった瞬間が一番気持ちいいです。
前日は競技開始直後何をするのかや最後の1時間は調整のみにするなどを決めました。
本番でやったこと
スコアは覚えている範囲になります。本番で使用したリポジトリはこちらです。
https://github.com/anko9801/isucon11
8:30 起床
ISUCON優勝!!
9:45 オープニング
今回のWebアプリ「ISUCONDITION」の紹介動画に爆笑していました。
10:00 競技開始
事前に話し合って最初は全員でマニュアルを読み込みました。認証周りがよくわからなかったけれど本筋理解しておけば大丈夫だろうと飛ばし読みしました。
10:49 初期スコア 1700
MySQLやNginxの設定ファイルや事前に用意したMakefileを書き込んで各種解析ツールをインストールしました
11:01 秘伝のタレを流し込む 2000
事前に用意していたMySQLとNginxのパフォーマンスを上げるような設定をしました
11:51 bulk insert
N個のINSERTクエリを1個のクエリにまとめるアプリの機能を使いました
12:00 昼食
13:05 静的ファイルをNginxでキャッシュする
htmlファイルや画像ファイルなど毎回同じレスポンスするものはNginxでキャッシュしました
13:14 DBに保存していた画像を剥がす
これは進研ゼミで出たやつでDBではなくファイルとして保存すると速くなります
13:59 COUNTを撲滅
SQLのCOUNT句は重いのでできる限り無くしました
14:02 コネクションプールの上限を上げる
DBのコネクションプールの上限を上げてクエリの実行を速く回せるようにしました
15:39 DBを分割 28000
pprofを見てみるとisu_conditionテーブル関連で重いのでこのテーブルのみを処理するDBサーバー、それ以外のテーブルを処理するDBサーバーを作ってここで処理させるようにしました。
15:55 INDEXを貼る 34000
スロークエリの結果を見てINDEXを付け足しながらEXPLAINしていい感じのINDEXを見つけます。最終的にこんな感じに貼りました。
CREATE TABLE `isu` (
...
INDEX user_index (`jia_user_id`),
INDEX isu_index (`jia_isu_uuid`),
INDEX character_index (`character`),
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `isu_condition` (
...
INDEX timestamp_index (`timestamp`),
INDEX isu_index (`jia_isu_uuid`),
INDEX isu_timestamp_desc_index (`jia_isu_uuid`, `timestamp` DESC),
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
16:29 再起動試験対策
ISUCON11では競技終了後に再起動して正しく動くかどうかを試します。ここで起動の順番はDBの起動がアプリの起動より遅いときに起動に失敗するので対策しないといけません。自分のチームではDBが起動するまで待ってあげるのと、念の為、失敗したらアプリを再起動させるという対策をしました。
16:54 ロードバランシング 37000
DBサーバーのCPUリソースが余っていたのでNginxからアプリを2つのサーバーで動かすようにしました。
17:31 ログをオフにする 40000
18:42 画像をSELECTしないようにする 42000
基本的にアプリとDB間の通信量を少なくすれば速くなるのでSELECTで画像のような大きくて不要なカラムは持ってこないようにします
18:42 最終調整 40000
最後まで改善を入れようとしてバグ修正が終了3分前に終わってかなりひやひやしました
完走した感想
結果は予選敗退でした。やれることは沢山あったのですが、自分が上手く動けず反省しています。
今回の問題は全範囲をカバーしつつ、新しく学ぶことが多くあり良問だったと思います。それと過去問を解いてると同じ状態でもスコアが結構ブレたりしたのですが、本番のベンチのスコアはほとんどブレなくて驚きました。運営に感謝です!
まとめ
と言っても悔しい!!!来年は本選出場します!!!!
明日はUzaki君の「【緊急対談】今、めだかボックスについて語る」です!お楽しみに!