🔩 ねじき教室 Go と Web の教室

題材を読む

読了目安 約2分

ISUCON 12 予選 ISUPORTS の構造と、データが 2 か所に分かれている事情を押さえます。

この章の目次

ISUPORTS は、大会の順位表を提供する Web サービスです。 コードは isucon/isucon12-qualify にあります。

登場人物

サービスを使う主体は 3 種類です。

ロールできること
SaaS 管理者テナントの追加、テナントごとの請求額の確認
テナント管理者参加者の追加、大会の作成と終了、スコアの CSV 入稿
参加者大会一覧、大会ごとのランキング、自分のスコアの確認

テナントは、大会を主催する団体ひとつぶんの区画です。 参加者もスコアもテナントの中で完結していて、テナントをまたいで参照することはありません。

データの置き場所が 2 つある

この問題の特徴は、データベースが 2 種類あることです。

置き場所中身
MySQL(管理用 DB)tenantvisit_historyid_generator
SQLite(テナント DB)playercompetitionplayer_score

SQLite はテナントごとに 1 ファイルです。 tenant_db/1.db のように、テナント ID がそのままファイル名になっています。

Go
// テナントDBに接続する
func connectToTenantDB(id int64) (*sqlx.DB, error) {
	p := tenantDBPath(id)
	db, err := sqlx.Open(sqliteDriverName, fmt.Sprintf("file:%s?mode=rw", p))
	if err != nil {
		return nil, fmt.Errorf("failed to open tenant DB: %w", err)
	}
	return db, nil
}

MySQL は別プロセスなので、クエリのたびに通信の往復が起きます。 SQLite は同じプロセスの中でファイルを読むだけなので、往復がありません。 同じ「1 クエリ」でもかかる時間が違います。

スコアの決まり方

ベンチマーカーは、参加者がランキングを見るなどの操作に成功するたびに加点します。 レスポンスが速いと参加者の数を増やし、遅いと参加者が離脱します。 1 リクエストを速くすると、次はもっと多くのリクエストが飛んできます。

計測に使った環境

  • アプリ・MySQL・nginx がすべて同じ 1 台に載っている(2 vCPU、メモリ 4 GB)
  • ベンチマーカーの走行時間は 60 秒
  • 初期実装のスコアは 6072

以降の章のスコアは、この環境で測った値です。