ISUCON10に参加してきました〜!

こんにちは, yapattaです!

今日はISUCON10(いい感じにスピードアップコンテスト)に参加してきました!!

点数は1122点です!

[追記]

学生内10位になり本戦出場できました!嬉しいね!

チームメイトはreudとたかひろさんです.

僕らのチーム名は「ワンランク上のジロリアン」です!! なんでそんな名前になったんでしょうね??

では早速, 僕らが8時間で何をやったか記載していきたいと思います!!

やったこと

リストに上げていきます.

  1. サーバーの構成確認
  2. ssh config設定
  3. NewRelicを噛ませる
  4. NginxでBotを503に投げる
  5. Nginxの設定見直し
  6. MySQLの設定見直し
  7. Where句の最適化
  8. index貼り
  9. goroutineで投げまくる
  10. MySQLの並列化(2台)

では具体的に一つ一つ見ていきましょうか〜

1, サーバーの構成確認

ちゃんと(公式のドキュメント)https://gist.github.com/progfay/25edb2a9ede4ca478cb3e2422f1f12f6は見ましょう. 要件確認は最重要項目です. 制約を見る力がAtCoderで鍛えられたと思います, きっと.

2. ssh config設定

踏み台サーバーを経由して, webserver群にアクセスする必要があります. .ssh/configに設定を書くとそこいらへんが非常に楽になります.

Host isucon-bastion
    HostName 踏み台サーバーのIP
    Port 20340
    User isucon
Host isucon-server1
    ProxyJump isucon-bastion
    User isucon
    HostName server1のPrivateIP
Host isucon-server2
    ProxyJump isucon-bastion
    User isucon
    HostName  server2のPrivateIP
Host isucon-server3
    ProxyJump isucon-bastion
    User isucon
    HostName  server3のPrivateIP

またトンネルを掘ってポートフォワーディングすると, プライベートネットワーク内のwebserverにhttpアクセスできます. 以下例↓

ssh -L 8888:10.163.89.101:80 isucon-server1

ローカルの8888ポートにプライベートネットワークの163.89.101:80をバインディングしている例です.

www.kmc.gr.jp

3. NewRelicを噛ませる

遅いエンドポイントがわかりました. まあそうだなという感じでした.

4. NginxでBotを503に投げる

Botからアクセスが来たら正規表現で判定して, 503 Server Unavailableに投げます

if ($http_user_agent ~* "^ISUCONbot(-Mobile)?$") {
      return 503;
}

上が例ですね.

5. Nginxの設定見直し

静的ファイルをキャッシュした. README見たら意味がないことに気づいた. 制約はちゃんと見ましょうね.

あとは, worker_rlimit_nofileを30000にして, worker_connectionsを7500にしました. いっぱいコネクションを張れそう.

6. Where句の最適化

estateを取り出すwhere句が冗長だったので, 最大最小を考えて条件を半分に減らした.

hd := h
if h > d {
    hd = d
}

みたいなイメージです.

6, Index貼り

DBのIndexを貼りました. 少し早くなった気がします.

7. goroutineで投げまくる

これがめちゃめちゃ早くなるのに貢献した. 並列化できそうなところでとりあえずeg.GOでgoroutineに投げて, eg.Waitで最後に並列処理を回収しまくった.めちゃめちゃ早くなった.

8. MySQLの並列化(2台)

SQLサーバーを並列化しました. 大層なことを言っていますが, クラスタを組んだわけでもなく2つのSQL Serverをただ起動したです. つまり全く違うDBにクエリを投げてもデータの整合性が取れそうなところでそれぞれのDBにクエリを投げて処理を分散させています. goでdbのインスタンスを2つ持つという鬼畜ぶりです. まあとりあえず早くなったから良し.

コンテスト後にDiscordを見てやっておきたいなと思ったこと

  • クエリキャッシュ
  • 空間インデックス
  • AppArmer
  • Geometryのライブラリを使う
  • Chairのいらないクエリを削除
  • MySQL Server8系統を使う
  • Redisを使う?
  • nazotteを計算量最適化
  • generated columnsを使う
  • popularityをマイナスにする(idとpopularityをマイナスにできる)

感想

楽しかった. 前日話し合ったことが結構役に立った. goroutineに感動した. 並列化は正義. 疲れました, おやすみなさい.