isucon9予選で赤い彗星になれず予選落ちしました
参加して赤い彗星(ソロで3人分の仕事する)になれませんでした。
https://github.com/d0riven/isucon9-qualifier
DL;DR
全体
- 14:30まではは30位くらいの中堅を維持してワンチャンあるか?という調子だった
- 複数台構成に切り替えた辺りで一気に詰まり失速し、そのままベンチ通らない状態が続く
- 単騎構成に戻すもエラーが解消できず0完
- 複数台構成に対応までのNewrelic Overview
スコア
- 最高: 3650 (14:30時点)
- 最終: 0 fail
チーム構成
- ソロで参加
- 理由
- ひとりの方がなにかと気が楽
- 練習時間わざわざ集まるとかやる必要ないし
- 開発環境の用意とかせず本番で確認できるし
- 自分の都合で予定がつかなくなるときも多い
- 全部自分で触る必要があるので色々触れて面白い
- 複数人でやるアドバンテージは筋力でカバーできるようになりたかった
- ひとりの方がなにかと気が楽
事前準備
- 1ヶ月半前から準備
- 以下の過去問練習
- isucon6予選
- isucon7予選
- isucon8予選(これはあんまりやれてない)
- isucon7に関して1台構成でやり切るところまで突き詰めた
- 複数台構成に関しては練習が出来ておらず
- nginxの設定ファイルをどうすればいいかくらいまでしか見れてなかった
- 同一OSであるisucon7のデプロイ & プロビジョンスクリプトをベースにisucon9ではそれを使った
- プロビジョニングはansibleというのも考えたけどDSL覚えるのも大変だし、OSも明らかだったのでMakefileで十分と判断
環境
記述以外は特にいじらず
参加しての所感
- 問題はisucon8予選ほどのアプリケーション改修の重さは感じなかった
- isucon8予選をやっていたときは、これ出されたらちょっと勝てないなと思うくらいにget_eventの把握と改修が大変だったため
- 年々isuconの問題の練度が上がっていて出題者に感謝
- 事前準備のおかげもあって1台構成でモニタリングからチューニングまでは特につまらずにいけた
- ただ事前に更に仕込んでおけばもうちょっと早くできる気もした(鍵の配布とか)
- 複数台構成に手を付ける前はワンチャンあるか?と思っていたが、そんなこともなく無念の0完
- 脳内ではキャッシュ化や外部APIをいい感じにすればもっと伸びそうかもとか妄想はしてた
- 複数台構成の部分で色々と考えが抜け落ちている部分があり苦戦
- MySQL8にはついでにアップグレードしておいたので、周りの人たちがハマったりしてたbind_addressに引っかかったわけではない
- 単純に複数台構成における知見がなさすぎた
- ソロで学生が両日トップを取っていて自分のダメっぷりを感じたが、結果は不思議と受け入れられたので黙って精進しようという気持ちになった
時系列
本番中にやりながら記録したもの。 複数台構成あたりからすんなりいかなくなりやりながら書く余裕なくなった。 後から思い出しで追記。 追記は 斜体 で記載
- ~ 10:20
- マニュアル読み
- ~ 10:30
- インスタンス作成
- 検索で絞っていたので複数台作ったのに見えなくて焦る
- ~ 10:45
- 鍵設定
- ~ 11:00
- git設定
- ~ 11:15
- 軽く休憩
- ブラウザでアプリケーションで動作確認
- shipment & payment service や initializeの疑問にぶち当たる
- ~ 11:40
- ~ 11:55
- payment04.isucon9q.catatsuy.orgが遅いことが主な原因であることも特定
- どこにアクセスしているかが不明
- docsを読むことに
- ~ 12:40
- shipment,payment0{1~5}までの間の外部サービスがランダムに使われることがわかった
- 後から見るとこれ30くらいまで増えているの確認できたのでスケールされてたっぽい
- おそらくだが、initializeで渡されたpaymentサービス以外は利用できない仕様になっているっぽいので分散も不可能
- transactions.jsonはマイページの取引一覧 + 詳細の表示に利用されている
- 外部サービスを使わない方向にシフトするのが良さそう?
- transaciton()の処理が何をやっているかをしっかり読んで外部サービスを極力使わない方向にシフトさせる? or 複数台構成を急ぐ?
- shipment,payment0{1~5}までの間の外部サービスがランダムに使われることがわかった
- ~ 13:15
- https://github.com/d0riven/isucon9-qualifier/commit/36e94925f7235a595a8ac90ec2bfaae97b158a1f
- shipment serviceに問い合わせずにshippingsテーブルを利用するように修正
- この時点でCPU使用率が100%になっており、CPU Boundっぽい感じなのを確認
- score:2650
- ~ 13:40
- https://github.com/d0riven/isucon9-qualifier/commit/fca0662ea6100ec2d1ec5db15fc4818b154b710a
- /new_items/{id}.json が遅いのを確認
items select
を高速化する- index貼ったが効かず、スコアの変更がなかった
- ついでにmysql8にupgrade
- ~ 14:10
- 消したはずのshipment serviceの問い合わせが元に戻るという自体に
- 理由が分からない
- おそらくだがpush漏れ
- ~ 14:30
- https://github.com/d0riven/isucon9-qualifier/commit/2dbd0f09899d57469d534df5140c6010f2c297ac
- items select のindexを再度調整
- score 3650
- 3650取ったあたりのOverview
- DB+Externalを3~4割くらいまでは抑えられるようになった
- ~ 14:45
- new_itemsのcategoriesの選択が多かったのでcategoriesのparent_idにindexを付与
- しかしスコア変わらず
- これも今見るとpush漏れによるデプロイミスだと思う。すくなくともparent_idでの検索の負荷は減るはずなのになぜか減っておらず疑問だったのを覚えている
- ~ 15:30
- DBの負荷も減ってCPUバウンドになってきたので複数台構成の方向に舵を切る
- ここから下は全部追記
- sellやbuyなど外部APIの情報はしっかりDBに入っていた
- ここを高速化するとなると問い合わせ方法の最適化をするので結構時間かかりそう
- CPUも100%使ってるし複数台構成にすればスコア倍は稼げそうな気がすると判断した
- 1台をDBサーバに、2台をアプリケーションサーバにする構成
- アプリケーションサーバが問い合わせを受けてnginxでLBさせた
- 作業ブランチ
- ~ 16:30
- ベンチ通らずセッションが共有できてないことに気づく
- Redis環境構築
- PHPのRedisでセッション共有する方法をググりつつ導入
- 初期化でRedisクリアするようにした
- ~ 17:00 (ここらへんからうろ覚え)
- セッションを共有するようにしたがそれでもログインが通らない
- DBの初期化ファイルがアプリケーションサーバのうち1つしかないことに気づく
- ~ 17:20
- /sell で500エラーが出ていてベンチ通らず
- nginxのerror.logには何も出ておらずお手上げ
- この時点で0完も覚悟
- ~ 18:00
- スコアが0なのもあれなので単騎構成に戻して帰ること
- しかし、ベンチが/sellで落ちて通らない
- サーバに前の設定が残っていたのを戻しきったつもりだがそれでも通らず
- そのまま0で終了
スコアの遷移
複数台構成以降は後から追記。
- 初期実装
- 1410
- newrelic & netdata 導入
- 1110
- transactionsでshipment serviceに問い合わせるのをやめる
- 2650
- items selectにindex貼ったが効かず
- 2650
- shipment service復活
- 1110
- items selectでindex貼る
- 3650
- categoriesにindex貼る
- 3650
- 複数台構成
- 0 (fail)
- 単騎構成に戻した
- 0 (fail)
来年の意気込み
やはりまだまだインフラもコードも雰囲気でやっている感がある。 土壇場だと結局経験値がものを言うが、今回は複数台構成の構築においてインフラ知識の経験値の少なさが露呈した。 来年は以下を鍛えて懲りずにソロで望みたい
またデプロイ周りの問題で巻き戻しが発生したり、バージョンを戻して管理されていた設定ファイルが管理されていない状態になると設定ファイルがそのままになるという状況もなんとかしたい。