ISUCON11予選に参加しました
4年連続4回目、いつものメンバーでISUCON11予選に参加しました!
ちなみに昨年の内容はこちら。
年に1回、ISUCON参加の記事を書くだけのブログになってきてしまったw
結果は今日の14時発表予定なのでそれを楽しみにしつつ、昨日一日でやってきたことを振り返りたいと思います。
準備したこと
今年はほんとに準備不足でしたが、毎年継ぎ足ししてきた秘伝の自動化・環境構築スクリプトがあったので、軽く使い方を振り返ったぐらいでした。
こんな構成のやつ
├── Makefile ← デプロイやツール類の操作、設定ファイルの反映などすべてMakefile経由で ├── bin ← goのビルド結果ファイルを置くとこ ├── etc ← 各種OSとミドルウェアの設定ファイル ├── logs ← 取得した各種ログの置き場所 ├── scripts ← アプリやミドルウェア、プロファイリングツールを操作する系 ├── src ← アプリの実装 └── www ← 静的コンテンツ
さすがに4年目ともなるとめちゃくちゃ便利にできあがっていて、今回しっかり使いこなせて便利すぎました。
sshログインしなくても
- Goのビルド
- デプロイ
- nginx, mysql設定ファイル変更&デプロイ
- nginx, mysql あたりのリスタート
- nginxのログ、mysqlのスロークエリログのON/OFF切り替え
- kataribe、pt-query-digest取得
などができるものです。おすすめ。
当日の流れ
10時スタートだったので9時に集合。Google Meetで話しながら進めていきました。
10:00 〜 11:30
- ガイドラインの熟読
- システム構成の把握
- 初期スコア確認
- もろもろGit管理
- モニタリング実施/ボトルネック検出
- kataribe
- pt-query-digest
- dstat
- ローカルからリモートを操作するスクリプト準備
- アプリデプロイ
- MariaDB設定変更
- Nginx設定変更
構成は
- Nginx
- アプリケーション実装
- MariaDB
という比較的シンプルな構成だった模様。
大体準備は整ったので、全体を見つつ明らかにまずいとこを修正。
isu_condition
テーブルにインデックス追加
【スコア】1,858 → 7,668
11:30 〜 12:10
手分けしていろいろ対策。
- Nginx/Go/MariaDBが1台に入ってる構成から、MariaDBを分離(2台構成)
- Nginxのproxy_buffer_sizeなど設定(エラーログに
drop post isu condition request
などが出てた) isu_condition
テーブルにインデックス追加- jiaServiceURL の値をDB使わずにローカルキャッシュに
DB分離とインデックス追加まわりが効いてそれなりにスコアアップ。
【スコア】7,668 → 25,290
12:10 〜 12:30
isu_condition
で複数レコード取得してるけど最初の1件しか使ってない箇所のクエリを LIMIT 1指定
不必要にデータを取得してる箇所を修正してちょっとスコアアップ。
【スコア】25,290 → 35,225
12:30 〜 13:10
isu
から不必要にimageデータを取得してるクエリを見直し- デフォルトアイコンのデータをメモリキャッシュ
- postIsuCondition内の処理をBULK INSERT
- dropProbabilityを0.8に
imageデータの取得にコストがかかってそうだったので、 SELECT *
を個別のカラム指定で。
でもそこまでスコアには影響なかったかもしれない。
BULK INSERTがちょっと効いてさらにスコアアップ。
【スコア】35,225 → 42,119
13:10 〜 17:00
isu_condition
のimageデータをローカルファイル保存に変更isu
テーブルにインデックス追加- 不要なトランザクション削除
- DBをもう一台追加、
isu_condition
のみ新しいDBで処理
この時間は停滞…。
imageデータのローカルファイル保存とか効果あるかなと思ったけど全然で。
isu_condition
へのクエリ操作がコスト高いのは分かってたので、そのテーブルだけ別DBに切り出ししたりも。
ただいくらやってもスコアアップしなくて、ブレイクスルーが必要だなと17時ぐらいに一旦冷静に状況判断してました。
【スコア】42,119 → 38,066
この時点までのグラフはこんな感じ。
17:00 〜 18:45
getTrend
の処理を効率化(characterをわざわざ取得しないで、isu
テーブルを全件取得して処理)SetMaxIdelConns(10)
を追加getIsuConditionsFromDB
でconditionLevelが3以上の場合はクエリ実行時にLIMIT
を追加- dropProbabilityを0.8から0へ
17:45終了予定が、ベンチマークが動かないというトラブルが発生し1時間延長に。
ここで最後にいろいろ試して、結果的に getIsuConditionsFromDB
のクエリに LIMIT
つけるのが大正解に!
ラスト20分で、 dropProbability
を0.8から0.1刻みで減らしていったらどんどんスコアが上がっていったときが、一番の盛り上がりでしたw
【スコア】38,066 → 147,684
まとめ
というわけで時間延長がなかったらかなりヤバい状況でしたw
ただ4回目ともなると、それぞれが得意領域で対策しながらスコアアップしていけたので、良いチームワークだったなーと。 過去イチやりきった感があったので、あとはもう結果を座して待つ、といったところです。
あとDiscordで行われている感想戦が参考になりすぎますね!
DESC
のインデックスが効かないとこをgenerated column
でunixtime*-1
してインデックスを貼る
それ!! DESC
が効くMySQLに切り替えるか考えてたけど、前のISUCONでも話題に上がってたこの方法があったの忘れてました…
trendはvarnishで0.8秒キャッシュ(ttl)、0.2秒grace
キャッシュまわりは正直仕様が理解しきれず手を出さなかったです。すごく参考になる話
静的ファイルにしたiconはX-Accel-Redirectレスポンスヘッダーで返すことで認証通しつつファイルを返しました。でもそんなにスコアに直結しなかった気がする
こんな手が…!これは業務でも普通に使えるやつですね! マネフォさんの解説がわかりやすかった
というわけで、やっぱり今回も最高に楽しかったです! 運営の皆様、本当にお疲れさまでした…!!!
追記 2021/08/22 14:16
結果出ました。
スコア的には本選いけてたのに、追試で画像が出なくて失格に…
画像の保存先を /tmp
にしてしまった自分の凡ミスです。ほんとに申し訳ない気持ちでいっぱい…😢
ちゃんと対応してる内容が追試に耐えられるものか確認すべきでした。猛省します。。。