しるろぐ

いろいろ書きます。

isucon2に参加してきました #isucon2

NHN主催のisucon2に参加してきました。
チーム名は「飲兵衛ズ」。チームメイトは、@karupanerura@masasuz

結果

惨敗でした。
午前中すぐに1000チケット超えて、しばらく1位だったのですが、いろいろ試してたらスコアが落ちてしまって、最終的に午前の記録を抜くことができませんでした。その間に他のチームにあれよあれよと抜かれてしまいました。

やったこと

太字が自分がやったことです。
後半、情報共有がおろそかになって、記憶を頼りに書いているので、誰が何やったとかちょっと曖昧。

10時

  • @karupaneruraIRCとnopasteを立ち上げる
  • IRCにnopasteの通知が来なくて困る
    • 結局手動でコピペすることになったが、ここはもうちょっと落ち着いて通知できるようにしたほうが良かった
    • コピペが面倒で情報共有がおろそかになった気がする
  • @masasuzgoogle docsに調査系でやりたいことをまとめる
    • 焦ったときに基本に立ち戻れたので助かった

11時

  • 初回ベンチ。チケット500枚ぐらい。
  • sshがめんどいので、.ssh/configにいろいろ追記してssh rev, ssh app01とかで入れるようにする
    • 個人端末と各サーバを好きに行き来できるようにしたけど、今思うと失敗だった
    • ちゃんとrevを踏み台にしてそこからしかデプロイできないようにしたほうが良かった
  • @karupaneruraがappとか設定ファイル系をまとめてgit管理にする
    • karupanerura++
  • デプロイツールを作る
    • appディレクトリをappサーバに配ったり、my.cnfをdbサーバに配ったりするやつ
  • @masasuzがpt-query-digest, dstatを入れる
  • というのを受けて、screenを入れて全サーバをdstatするやつをscreen -xでみんな見れるようにする
  • @karupaneruraがnginxを入れる
  • @masasuzは重いクエリを探す

12時

  • mysqltuner.plとか実行しつつ、my.cnfを調整する
    • デプロイしてmysql再起動。
    • disconnectしてなくてapp再起動しないといけないのにちょっとはまる。チケット730枚に。
  • @masasuzが明らかに不要なrand()を消す。チケット1200枚で1位に。
  • mysql再起動したときに全部のデータがbuffer poolに乗るようにする
    • ベンチするときは毎回全部起動しなおして条件を同じにする方針だったが、たまに再起動わすれたことがあって、ベンチ結果が揺れたかも
  • @masasuzがappのrestartスクリプトを書く

13時

  • 更新が多いのでダメとは思いつつもquery cacheを入れる
    • 750枚ぐらいになってダメそうなのですぐに元に戻す
  • @karupaneruraがrevをnginxに替える
    • チケットは950枚になったが、後々静的ファイル配るようにするからそれで性能あがるよねという話になりnginxにしたままに
    • 結局静的ファイル配らなかったので、その時点で元に戻せばよかったかも
    • このときから何か、歯車が狂い始める
  • @masasuzが定期的にpt-query-digest
  • お昼ご飯食べる
  • redisにしたらどうかというアイデアが出たが経験不足で怖いのでやめた
  • サイドバーキャッシュしてワーカーで定期的に更新させるといいんじゃないかなという話になりそこら辺を@karupaneruraがやることに
  • といいつつ@masasuzがmemcachedを立てる

14時

  • ベンチ回すための準備が面倒だったので、一発でそれぞれのサーバに必要なファイルを配りつつ、db, appを再起動してくれる君を書く
  • indexとか追加するも、逆に性能落ちる
    • あとからexplainしたら追加したindexがうまいこと使われていなかったらしい
  • nginxで静的ファイルを配るようにしたが思うように性能が伸びない
    • この時点でもう少し調査するかnginxをやめるかという話し合いをすればよかった
  • そして何が入ったのかよくわからないがベンチ回したら700チケットぐらいに落ちてた。なぞい
    • と思ったが追加したindexをisucon2.sqlをrevertしただけでdropできたと勘違いしていたぽい
    • ので、nginxの静的ファイルで性能落ちたというのは勘違いだったかもしれない
  • この時間はみんながいろいろ試してて何がどうなってたか全然把握してない
    • macからデプロイできるようにしていたのでpushせずにデプロイ&ベンチとかしていて、何を入れてどうなったとかが謎
  • で、このへんからぼくがデプロイ&ベンチまわりを全部取り仕切ることになった

15時

  • buyするところでselectしてからupdateするようにする
    • 700から一気に1300チケットぐらいになったが、csvにorder_idがないよと言われる
    • シーケンシャルに席取るので同時に購入が走ると上書きされてしまう
  • ということで、SELECT FOR UPDATEに替える
    • こけなくなったが700チケットに戻ってしまった
    • ちなみにここで pt-query-digestをしたら、このSELECT分で50%だった
  • buyを直そう!みたいな感じになってみんなbuy見てて時間の無駄だった。もったいない
    • もっと抜本的なところから治せばよかった
  • アイデアとしては、いろいろあがった
    • 空いてる席一覧をとってきてapp側でrandするとか
    • 空いてる席一覧をキャッシュにいれて、それを一個ずつ取り出していくとか
    • これこの場でupdateする必要なくね?とか
    • あがったけど、みんな牽制しあって何もやらなかったのがすごい悔やまれる
  • dstatとか見てたらだいぶすかすかだったので、rev, dbにもappをたてる
    • 性能あがったが、なぜかapp立てる前のベンチが300とかになっててそれが600ぐらいになったみたいな感じだったはず
    • 気づくと謎に性能落ちてて本当に謎

16時

  • @karupaneruraがキャッシュ周りをひたすら作る
    • が、性能落ちたらしい(やってたの知らなかった)
  • 自分はselect周りを色々いじくってたけどうまく行かず
  • という上の作業が実は同時にお互いベンチやっていたっぽくて、多分もしかしたらキャッシュうまくいってたのかも
    • 今回は本当にデプロイまわりの戦略がだめすぎた。原因が追えない
  • で、キャッシュは一旦置いといて、ワーカー周りを@karupaneruraが担当
    • 結局うまく動かなくて、ワーカーに投げたりしてるけど、結果を使ってない、みたいなもったいないことになった
  • そして気づいたら300チケットとかに落ちてた。なぞい。何が入ったの!
  • そしてこのときをさかいにIRCのログが途絶えてる……

17時

  • where区いじったりindex追加したりする
    • 300が700になった!とかで喜んでたがひどすぎる……
    • しかも気づくとまた300とかになっててそれをまた700にするような改善してた
  • @karupaneruraはrecunt_soldをワーカーであっためるの頑張ってた
  • キャッシュとかちょっと間に合わないだろうなと思って、手軽なorder_id IS NULLを撲滅する

18時

こんな感じで終了。キャッシュもワーカーも入れたはいいけど活用してない、とかでだいぶ勿体ないことをした。
みんな焦ってしまって、すぐに結果出さなきゃという意識が強かったために、時間をかけて着実に実装するというのができていなかった気がする。
あと、今思うと本当に不思議なんだけど、ローカルで動作確認していなくて、ベンチで動作確認していたのが、いろいろな待ち時間とかコンフリクト発生させていて無駄だった。

正直、自分はデプロイツールとmy.cnfで燃え尽きた感ある。

反省点

それぞれ上に細かいことは書きましたが、総評としては次のような感じ。

話し合いが足りなかった

もっとじっくり腰を落ち着かせたかった。一人が細かいチューニングしてもうひとりが全く別のことやる、みたいなことをしてよかったかも。山形組すごい。

作業者が多すぎた

それぞれの環境からデプロイできるようにしていたので、デプロイがかぶったりして、配ったはずのファイルがない!みたいなことが何度かあった。
あと、各々好き勝手にpushしていて、一回のベンチで複数の変更が入ったりしてしまった。何が原因でベンチ結果が変わったのかわからなくて、原因調べるためにrevertしたのに、元の結果に戻らないとか。今思うとindexの追加とかミドルウェアの変更とかgitで追えないところに遅くなった原因があったぽい。
で、後半はぼくがデプロイとかベンチをとりまとめる、みたいなことをやったけど、あまり徹底されてなくて何度かデプロイかぶったりした。

誰が何をやってるのかわからなかった

情報共有用にIRCを用意したんだけど、途中から全く使われなくなって、スコアの変遷とかも午後の記録全くない状態だった。「ベンチしたら変更点とスコアをまとめる」みたいな決め事をしておけばよかった。
他にも、遅い原因の共有とかもされなかったので、みんなで同じところを修正していたなんてこともあった。
後半、IRCが独り言状態になって悲しかった。

git管理外のもろもろが追えない

gitで管理している分は変更を追えるのでいいんだけど、ミドルウェア変えたとかALTER TABLE打ったとかいうのが追えなくて困った。
特に、クエリの改善×ミドルウェアの変更の両方が同時に入ることがあって、片方ずつ元に戻してまたベンチ回す、みたいなのがだいぶ時間の無駄だった気がする。

経験不足

やりたいことはたくさん浮かぶんだけど実装が間に合わなかった。

次回参加するとしたら

  • 準備は多分全チームの中で一番早かったと思うので、この調子で頑張りたい
  • 一人は完全に調査&ベンチする人にしてしまって、他の二人にタスクを投げる形式にしたい
  • 変更点とスコアをペアできちんと記録するようにしたい
  • もう少し、方針的なことを話し合う時間を持ちたい
  • schemaもgit管理して毎回作りなおしたい
  • もっと経験つみたい

最後に

楽しかったです!!ありがとうございました!!