ISUCON8予選1日目にチーム「SELinuxはEnforcing以外あり得ない」で参加して最終スコアは26,221でした
もはやこのブログはISUCON参加記に成り下がってしまってますが。
今年も@ishikawa84g 、@netmarkjp、@matsuuの3人でISUCON8に挑んできました。このスコアじゃ今年も本選進出は難しそうですね。がっくし。
チーム名のとおり、DisabledだったSELinuxはEnforcingにしてフィニッシュです。
やったこと
3人で作業分担をしてたので、基本的に自分がやったことをまとめます
- ベンチ前の準備スクリプトとベンチ後の集計スクリプト(kataribe, pt-query-digest)を用意
- getEvent内のN+1をやっつける
- ORDER BY RAND()を消してみたもののランダムじゃないと怒られるので差し戻し
- sheetsは増減しない上にsheet_idから算出できるので、できるだけ利用しないように実装変更(sheetsひっぺがし)
- /api/users/:id のN+1をやっつける
- 残席数(remain)はeventsにカラムを追加して格納するように変更したものの、デッドロックが発生するのでremainsテーブルを別途作成して格納するように(しかし最終的にfailになるので差し戻し)
- /api/events/:id/actions/reserve 内の ORDER BY RAND() をやらないために全sheetに乱数のカラムとインデックスを追加してソートするように(しかし最終的にfailになるので差し戻し)
- 1台目のh2oとwebappとmariadbはそのまま、2台目と3台目にwebappを稼働させ、/initializeのアクセス以外は2台目と3台目に振るように実装変更(しかし最終的にfailになるので差し戻し)
まとめ
上記スクリーンショットにもあるとおり、直前でもsuccess/failしておりなかなか厳しい内容でした。
今回はトランザクションをきちんと意識した上で改修できるかが肝だったとの認識なのですが、ある程度性能が上がってくるとfailが発生してしまい、結局古いコミットにまで差し戻して(それでもたまにfailが出る)無難なスコアでフィニッシュせざるを得ない苦しい展開でした。つらい。
自分で変更した実装に問題があった可能性が9割以上あるのですが、もしかしたらGo実装でgetEvents内のgetEvent呼び出しが同一トランザクションになっていなかったのがある種の罠になっていたのではないかと考えています。もしかしたらgetEventsのN+1を退治すれば結果として解消したのではと思うと、うーん悔しい。問題が公開されたら追試しようと思います。
手を抜く実装にしたらしっかりベンチマーカーが検知しててムムムやるな、と思わず唸る良い実装だったと思います。すべてのサーバーサイドプログラマーはトランザクション処理とはどういうことかというのを学ぶ良い教材になるのではないでしょうか。みんな過去問やろうな。