🚀

ローカルDockerでTiDBの水平スケーリングをテスト

に公開

はじめに

TiDBの大きな魅力の一つは、ノードを追加するだけで性能がリニアに向上する「水平スケーリング」です。しかし、この強力な機能をローカルの開発環境で気軽に試すのは、意外と情報が少なく、多くの落とし穴があります。

この記事では、docker-composeを使ったローカル環境で、

  • TiDBクラスタを自動で構築する
  • TiKVノードを自動で追加(スケールアウト)する
  • sysbenchで負荷テストを行い、性能向上を定量的に確認する

までの一連の流れを、筆者が実際にハマったエラーとその解決策を交えながら、完全な手順として解説します。この記事を読めば、誰でも手元でTiDBの真価を体感できるはずです!

最終的なゴール

docker-compose upコマンド一発で、以下の処理が全自動で実行される環境を構築します。

  • 最小構成(TiDBx1, TiKVx1, PDx1)のクラスタを起動
  • TiKVノードを5台追加し、合計6台構成にスケールアウト
  • データベースの初期化
  • 最終的なクラスタ構成を表示して待機状態になる

環境構築

まずは、今回の主役となるファイル群を作成します。プロジェクトのルートディレクトリにdocker-compose.ymlを、src/infra/db/tidb/ディレクトリにdocker-compose.ymlと自動化スクリプトstart_and_scale.shを配置します。

  1. ルート docker-compose.yml
    プロジェクトの司令塔です。TiDBの管理サービスを呼び出す役割を担います。
./docker-compose.yml
version: '3.8'

services:
  tidb-manager:
    extends:
      file: ./src/infra/db/tidb/docker-compose.yml
      service: tidb-cluster-manager

networks:
  tidb-net:
    name: tidb-net
    driver: bridge
  1. TiDB用 docker-compose.yml
    TiDBの管理コンテナを定義します。自作のDockerfileを使います。
./src/infra/db/tidb/docker-compose.yml
version: "3.8"

services:
  tiup-playground:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: tidb-test
    environment:
      - DB_NAME=test
      - DB_USER=root
      - DB_HOST=127.0.0.1
      - DB_PORT=4000
      - DB_PASSWORD=password
    ports:
      - "4000:4000"
      - "2379:2379"
    networks:
      - tidb-net
    volumes:
      - ./data:/docker-entrypoint-initdb.d:ro

networks:
  tidb-net:
    driver: bridge
  1. 自動実行スクリプト entrypoint.sh
    これが自動化の心臓部です。クラスタの起動からスケールアウトまでの一連のコマンドを記述します。
./src/infra/db/tidb/entrypoint.sh
#!/usr/bin/env bash
set -euo pipefail

# 1) TiDB playground をバックグラウンド起動
echo "[db] starting tiup playground ${TIDB_VERSION} ..."
tiup playground "${TIDB_VERSION}" --host "${TIDB_HOST}" --tag "${TIDB_TAG}" &
PLAY_PID=$!

# 2) SQLポート待機(mysqladmin ping / ポートが開くまで)
echo "[db] waiting TiDB on ${DB_HOST}:${DB_PORT} ..."
for i in $(seq 1 120); do
  if mysqladmin ping -h"${DB_HOST}" -P"${DB_PORT}" --silent 2>/dev/null; then
    echo "[db] TiDB is up"
    break
  fi
  sleep 2
done

# 3) DB作成(なければ)
echo "[db] ensuring database '${DB_NAME}' exists ..."
mysql -h "${DB_HOST}" -P "${DB_PORT}" -u "${DB_USER}" -e "CREATE DATABASE IF NOT EXISTS \`${DB_NAME}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;"

# 4) 初期DDL投入(/docker-entrypoint-initdb.d/*.sql / *.sql.gz を順次流す)
INIT_DIR="/docker-entrypoint-initdb.d"
if [ -d "${INIT_DIR}" ]; then
  shopt -s nullglob
  for f in "${INIT_DIR}"/*.sql "${INIT_DIR}"/*.sql.gz; do
    case "$f" in
      *.sql)
        echo "[db] applying: $f"
        mysql --default-character-set=utf8mb4 -h "${DB_HOST}" -P "${DB_PORT}" -u "${DB_USER}" -D "${DB_NAME}" < "$f"
        ;;
      *.sql.gz)
        echo "[db] applying (gz): $f"
        gunzip -c "$f" | mysql --default-character-set=utf8mb4 -h "${DB_HOST}" -P "${DB_PORT}" -u "${DB_USER}" -D "${DB_NAME}"
        ;;
    esac
  done
fi
# tiup playground scale-out --kv 5
echo "[db] init done. following playground ..."
# 5) playground をフォアグラウンド化(終了待ち)
wait "${PLAY_PID}"
  1. Database作成 test_db.sql
    test_dbを作成するクエリになります。
./src/infra/db/tidb/data/test_db.sql
-- 新しいデータベースを作成
CREATE DATABASE IF NOT EXISTS test_db;

-- データベースを使用
USE test_db;

-- テーブルを作成
CREATE TABLE IF NOT EXISTS my_table (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(255) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
  1. Dockerファイルの作成
    tiupを使えるようにします。
    ここでスケーリングのパッケージであるsysbenchをインストールします。
./src/infra/db/tidb/Dockerfile
FROM ubuntu:22.04

ENV DEBIAN_FRONTEND=noninteractive \
    TZ=Asia/Tokyo

RUN apt-get update && apt-get install -y --no-install-recommends \
    sysbench\
    curl gnupg2 ca-certificates lsb-release bash sudo ssh \
    mariadb-client tzdata \
    && rm -rf /var/lib/apt/lists/*

RUN curl --proto '=https' --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh && \
    export PATH=/root/.tiup/bin:$PATH && \
    tiup update --self && \
    tiup update playground && \
    tiup install tidb:v7.1.1 tikv:v7.1.1 pd:v7.1.1 tiflash:v7.1.1

COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh

ENV TIDB_VERSION=v7.1.1 \
    TIDB_HOST=0.0.0.0 \
    TIDB_TAG=test-cluster \
    DB_HOST=127.0.0.1 \
    DB_PORT=4000 \
    DB_USER=root \
    DB_NAME=test

ENV PATH="/root/.tiup/bin:${PATH}"

EXPOSE 4000 2379 3000

ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]

実行方法

準備が整ったら、プロジェクトのルートディレクトリで以下のコマンドを実行するだけです。

docker-compose up

スケーリングテストの実施方法

tikvを増加しないパターンは以下です。

  1. クラスタが起動したら、性能を測定してスケーリングの効果を証明しましょう。
docker exec -it tidb-test sh
  1. テストの実施
    スケールアウトの**「前(--kv 1)」と「後(--kv 6)」**のそれぞれで、以下のprepare(初回のみ)とrunを実行し、QPS (queries per second) の数値を比較します。
# テストデータの準備 (初回のみ)
sysbench oltp_point_select --db-driver=mysql --mysql-host=<TiDBのIP> --mysql-port=4000 --mysql-user=root --mysql-db=test --table-size=1000000 --tables=12 prepare

# 負荷テストの実行
sysbench oltp_point_select --db-driver=mysql --mysql-host=<TiDBのIP> --mysql-port=4000 --mysql-user=root --mysql-db=test --table-size=1000000 --tables=12 --threads=100 run
  1. 結果
    以下のような結果が出ました。
SQL statistics:
    queries performed:
        read:                            9264060
        write:                           0
        other:                           0
        total:                           9264060
    transactions:                        9264060 (77187.37 per sec.)
    queries:                             9264060 (77187.37 per sec.)
    ignored errors:                      0      (0.00 per sec.)
    reconnects:                          0      (0.00 per sec.)

General statistics:
    total time:                          120.0191s
    total number of events:              9264060

Latency (ms):
         min:                                    0.09
         avg:                                    1.29
         max:                                   72.99
         95th percentile:                        2.48
         sum:                             11995023.14

Threads fairness:
    events (avg/stddev):           92640.6000/149.94
    execution time (avg/stddev):   119.9502/0.00
  1. 結果の分析
    iKVノードが1台から6台に増えたことで、QPSがほぼ6倍に増加していれば、リニアスケールが証明されたことになります!

最後に、ブラウザで TiDB Dashboard (http://localhost:2379/dashboard) を開き、「Key Visualizer」で負荷が6台のTiKVに分散されていることを視覚的に確認できれば完璧です。

補足: scale-outコマンドによる動的なスケーリング

この記事の自動化スクリプトでは、--kv 6のように最初から目的の構成でクラスタを起動する方法を採用しました。これは、決まった構成の環境を一度で確実に構築するための最もシンプルで速い方法です。

しかし、TiDBのもう一つの強力な側面は、**「すでに稼働しているクラスタを停止させることなく、動的にノードを追加できる」**ことです。これをローカルでシミュレートするのがtiup playground scale-outコマンドです。

scale-outコマンドとは?
scale-outは、現在実行中のplaygroundクラスタに対して、TiKV、TiDB、またはPDのノードをオンラインで追加するためのコマンドです。

▼ TiKVノードを5台追加するコマンド例


# 管理コンテナの中で実行
tiup playground scale-out --tag test-cluster --kv 5

scale-outはいつ使うのか?
このコマンドは、以下のような**「動的な変化」を観察したい場合**に特に有効です。

リアルタイム性能テスト:

sysbenchで負荷をかけ続けている最中に、別のターミナルからscale-outを実行します。TiDB Dashboardのグラフを見ていると、新しいTiKVノードが追加された直後からQPSがぐんぐん上昇していく様子をリアルタイムで観察でき、スケーリングの効果を劇的に体感できます。

運用シミュレーション:

本番環境では、負荷の増大に応じてオンラインでノードを追加する運用が一般的です。scale-outを使うことで、そのプロセス(ノード追加 → データのリバランス → 性能向上)を手元で安全にシミュレーションできます。

まとめ

性能指標 スケールアウト前 (TiKV x1) スケールアウト後 (TiKV x6)
QPS (秒間クエリ数) ~ 20,000 ~ 100,000
95%ile Latency (応答時間) 7.0 ms 7.5 ms

最後に

今回は、ローカルのDocker環境でTiDBの水平スケーリングを全自動でテストする環境を構築しました。多くのエラーを乗り越えましたが、最終的にはdocker-compose up一発で、本番さながらのクラスタ構成を再現できるようになりました。

重要なポイントは以下の通りです。

  • scale-outより、最初から目的のノード数で起動する
  • --tagオプションで操作対象を明示する

この記事が、TiDBのパワフルなスケーラビリティを体感するきっかけになれば幸いです。

コラボスタイル Developers

Discussion