今年も例年通り @matsuu、 @ishikawa84g と参加しました。 役割分担はこれまたいつも通りこんな感じ。
- @matsuu バリバリ実装する前衛
- @ishikawa84g サイトやレギュレーションやコードやログやDiscordを見る情報官
- @netmarkjp 司令塔
最終スコアは2837。 サーバ2台体制で、1台はnginxとapp、もう1台はDBです。 appはGolang、DBはMySQL8.0でした。
同じ場所に集まらずリモート参加。 Discordで音声をつなぎ、各自のデスクトップを配信して自由に覗ける・すぐに共有できるようにしました。 隣にいるのにかなり近い感覚でできてよかった。
具体的な実装の話は@matsuuが書いてくれたので、司令塔ポジションで今回ポイントだったところを。
- レギュレーション・マニュアル・サイト・アナウンス・ログをよく見て、正しい情報をもとに判断する
- わかっているボトルネックから目を逸らさない
前者は言わずもがな。 言わずもがなではあるんですが、とはいえなかなか実現するのは難しい。 @ishikawa84g がマジで優秀なので我々はいつも救われています。
ボトルネックも、気持ちはわかるけど実行するのは難しいのですよね。 今回はtop, dstat, slow query log(pt-query-digest)から、MySQLのCPU(USR)が支配的でした。 MySQLのCPU利用率が90%なのにサーバをわけても効果が知れているのと、時間的に構成変更は早すぎるだろうと判断してMySQLと向き合っていました。 slow query logを見つつ、CPU(USR)に効くことをコツコツ続けていって残ったのが、なぞって検索のクエリ。
いまだにMySQLのCPU利用率が90%とかなので、ここをなんとかしないとサーバを分散したりしてもイマイチです。
内外の判定をアプリでやる案も一瞬あがったものの、我々はそういうプログラミングの経験がなさすぎたので断念。
ST_Contains
をうまく使う方針としました。
Geo系の経験が全くなく「SRIDって何!?」だったのですが(なんだかしらんけど4055を指定するらしいぞ!?POINT型は0らしいぞ!?みたいなレベル)、時間内にMySQLの公式ドキュメントを読んだりぐぐったりしてなんとか空間インデックスをうまく効かせられるようになり、MySQLのCPU利用率が60%台くらいまで落ちてきました。 ここをなんとかできなかったらおそらく予選突破できなかったと思います。
いよいよ構成変更だということでDBサーバをわけて、最終スコアは2837でした。 スコアの感じから、予選突破の安全圏を3000overと想定していたので少し悩みましたが、残り20分で再起動試験がまだだったので再起動試験を優先。 最後にsystemdの設定変更が必要なことに気づき、なんとか予選突破できました。
DBの処理を2台に分散させられればよかったんですが、なぞってのクエリを分散させることにこだわりすぎた結果、もう一押しが届きませんでした。 何事も程度は重要。
わたしが実践している基礎知識や方法論などをまとめたのがWebエンジニアが知っておきたいインフラの基本です。 発売時のエントリに 「この本に書いてあることをきちんと実践できれば決勝進出はできます。間違いない。」 なんて書いちゃったんですが、いまだに本選進出できているのであながち間違ってないなぁなんて自画自賛しています。
そんなわけで2年連続で本選進出できました。 毎年楽しいコンテストを開いていただき、運営のみなさんには大変感謝しております。 本選もがんばります。